2011-04-20 75 views
3

鑑於下面的代碼,我看到不再需要關閉閱讀器或連接的finally塊(如果它仍然可用)。使用如此多的嵌套「使用」語句有什麼好處或缺點?還是我應該走最後的路線?使用「使用」太多?

List<string> platforms = new List<string>(); 

NpgsqlDataReader reader = null; 

try 
{ 
    using (NpgsqlConnection conn = new NpgsqlConnection(GetConnectionString())) 
    { 
     // Making connection with Npgsql provider 
     string sql = @"SELECT platforms.""name"" FROM public.""platforms"""; 

     using (NpgsqlCommand command = new NpgsqlCommand(sql)) 
     { 
      command.Connection = conn; 
      command.CommandType = System.Data.CommandType.Text; 

      conn.Open(); 

      using (reader = command.ExecuteReader()) 
      { 
       while (reader.Read()) 
       { 
        platforms.Add((string)reader["name"].ToString()); 

       } 
      } 
     } 
    } 
} 
catch (Exception err) 
{ 
    HandleError(err, "GetPlatforms"); 

} 
finally 
{ 
    platforms = null; 

    if (!reader.IsClosed) 
    { 
     reader.Close(); 
    } 
} 
+1

那麼,如果他們現在會添加「濫用(var ...)',語言看起來不正確? – corsiKa 2011-04-20 13:16:23

回答

8

它確保在使用塊完成時釋放資源。每MSDN

using語句允許程序員來指定使用資源的對象 應該釋放 他們。提供給使用 語句的對象必須實現 IDisposable接口。此接口 提供Dispose方法,其中 應釋放對象的資源。

A,使用語句可以達到使用 語句的結束既可以當或退出如果 拋出異常,並且控制葉 的 語句結束前語句塊。

我沒有看到你的代碼中列出的多個using語句塊有什麼問題。它確保資源的發佈和程序員不會忘記的方式。

如果你不喜歡identation,那麼你可以重新寫這樣的事情:如果您使用的是「使用」塊

using (StreamWriter w1 = File.CreateText("W1")) 
using (StreamWriter w2 = File.CreateText("W2")) 
{ 
     // code here 
} 

參見這太問題上nested using statements in C#

+0

有時甚至可以將'使用'對象滾動到一個語句中,*如果它們是相同的類型*。這不會幫助OP的情況,但是對於你的例子:'使用(StreamWriter w1 = File.CreateText(「W1」),w2 = File.CreateText(「W2」)){/ * ... * /}' 。 http://msdn.microsoft.com/en-us/library/yh598w02.aspx – LukeH 2011-04-20 13:21:56

+0

@LukeH:是的,好點! – 2011-04-20 13:22:33

1

最終沒有必要使用。

只是關閉讀取和連接。使用系統

understanding ‘using’ block in C#

代碼

; using System.Collections.Generic;使用System.Linq的 ; using System.Text;

namespace BlogSamples 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      using (Car myCar = new Car(1)) 
      { 
       myCar.Run(); 
      } 
     } 
    } 
} 

的代碼

.method private hidebysig static void Main(string[] args) cil managed 
{ 
    .entrypoint 
    // Code size  37 (0x25) 
    .maxstack 2 
    .locals init ([0] class BlogSamples.Car myCar, 
      [1] bool CS$4$0000) 
    IL_0000: nop 
    IL_0001: ldc.i4.1 
    IL_0002: newobj  instance void BlogSamples.Car::.ctor(int32) 
    IL_0007: stloc.0 
    .try 
    { 
    IL_0008: nop 
    IL_0009: ldloc.0 
    IL_000a: callvirt instance void BlogSamples.Car::Run() 
    IL_000f: nop 
    IL_0010: nop 
    IL_0011: leave.s IL_0023 
    } // end .try 
    finally 
    { 
    IL_0013: ldloc.0 
    IL_0014: ldnull 
    IL_0015: ceq 
    IL_0017: stloc.1 
    IL_0018: ldloc.1 
    IL_0019: brtrue.s IL_0022 
    IL_001b: ldloc.0 
    IL_001c: callvirt instance void [mscorlib]System.IDisposable::Dispose() 
    IL_0021: nop 
    IL_0022: endfinally 
    } // end handler 
    IL_0023: nop 
    IL_0024: ret 
} // end of method Program::Main 

IL正如你可以在這裏看到你使用塊被轉換的嘗試......終於。但類必須實現IDispose接口

+0

你也可以在C#參考中發現,不需要IL ... – 2011-04-20 13:36:49

+0

@亨克霍爾特曼 - 好的.................. – 2011-04-20 13:38:15

3

你確實知道如何編譯一個using

服用

using (var disposableObject = new DisposableObject()) 
{ 
    // do something with it 
} 

獲取的編譯(或多或少):

IDisposable disposableObject = new DisposableObject(); 
try 
{ 
    // do something with it 
} 
finally 
{ 
    if (disposableObject != null) 
    { 
     disposableObject.Dispose(); 
    } 
} 

只是一個想法:在哪些情況下可以例外發生的呢?

  • db不見了:你應該怎麼處理?
  • 查詢是錯誤的:......應該記錄

猜測:我想NpgsqlConnection電話.Close().Dispose()本身 - 但你必須驗證與如。 .net反射

因爲你已經通過評論問它:

  1. 我不認爲這是一個不錯的選擇,有一個很大的catch ...你明確地知道什麼可以去錯了 - 將其拆分爲幾個捕獲物
  2. 處理這些異常情況不會在日誌記錄中完成。根據環境(有狀態與無狀態),您需要處理它(重新創建連接,再次查詢......)。處於非有狀態的環境中,重試通常毫無意義......當數據庫消失時,您有哪些選擇?
  3. 這只是一個化妝品問題,還是你真的想知道發生了什麼?如果它是一個化妝品... pfuh ...如果它更多的核心,我不會在乎人們的答案,並與探查器追捕表現:)並會用反射工具進行一些調查
  4. 您的代碼基本上看起來很好 - 我沒有任何線索爲什麼你在乎太多的using聲明:) ...除了pt。 1
+0

對不起,我一定是想念一些東西每個人都會因爲他們在提高你的答案而得到答案。請您詳細說明一下,因爲我不確定您在「正義與理念」部分所說的內容。 – capdragon 2011-04-20 13:21:21

+1

看到我的編輯 - 希望現在越來越清晰 - 如果沒有,請打我! – 2011-04-20 13:31:56

+0

是的!更清晰。問題更多的是核心,但我從來沒有使用過探查器,所以我希望別人能告訴我。但是在你發表評論後,我想我會開始學習如何使用它。這是關於時間,我知道真的在發生什麼。 – capdragon 2011-04-20 13:51:00

1

我不知道除了代碼縮進之外的任何缺點。優勢很明顯,你不需要擔心處理你的物品,因爲一旦使用支架就會被丟棄。

我注意到在你的錯誤處理程序中,你傳遞的是類似於方法名稱的東西。對於更通用的,您可以通過添加到工具箱中來使用,或者創建一個代碼片段將類似於以下內容來自動選取方法和類名稱。你可以使用反射來獲得這些細節。

ErrorHandler.Handler.HandleError(ex, System.Reflection.MethodBase.GetCurrentMethod().Name, System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName); 
+0

+1 - 感謝您的錯誤處理提示! – capdragon 2011-04-20 13:18:45

+1

@capdragon - 沒有probs,我曾經這樣做,直到我發現了其他方法。節省很多時間:) – WraithNath 2011-04-20 13:19:54

0

我覺得你的代碼是很不錯,但我個人使用條款,以獨立的功能,而重構一個因爲具有5個連續的大括號(即})增加了代碼的readible。但這是我的觀點 - 我喜歡儘可能降低縮進水平。