簡體   English   中英

使用“使用”太多了?

[英]using “using” too much?

鑒於以下代碼,我認為不再需要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();
    }
}

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

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

當達到using語句的結尾或者拋出異常並且控制在語句結束之前離開語句塊時,可以退出using語句。

我沒有看到您在代碼中列出的多個using語句塊有任何問題。 它確保釋放資源,並確保程序員不會忘記。

如果您不喜歡這個標識,那么您可以重寫它,如下所示:

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

另請參閱關於C#中嵌套使用語句的此SO問題

你真的知道如何using get編譯嗎?

服用

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

get編譯為(或多或少):

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

只是一個想法:在哪些情況下會發生異常?

  • db消失了:你應該怎么處理?
  • 查詢錯誤:...應該記錄

猜測:我想NpgsqlConnection.Dispose()本身上調用.Close() - 但你必須用eg驗證。 .NET Reflector

正如你通過評論要求的那樣:

  1. 我不相信這是一個很好的選擇有一個大的catch ...你明確知道什么可能出錯 - 把它分成幾個捕獲
  2. 處理這些異常不是通過日志記錄完成的。 根據環境(有狀態與非有狀態),您需要處理它(重新創建連接,再次查詢,......)。 處於非有狀態的環境中重試大多沒有意義......當數據庫消失時,您有哪些替代方案?
  3. 這只是一個美化問題還是你真的想知道引擎蓋下發生了什么? 如果它是一個化妝品... pfuh ...如果它更多的核心,我不會關心人們的答案和用剖析器追捕表現:)並會用反射工具做一些調查
  4. 你的代碼基本上看起來很好 - 我沒有任何線索為什么你關心太多using語句:) ...除了pt。 1

如果您使用“使用”塊,則無需最終使用。

只是關閉讀取和連接。

理解C#中的“使用”塊

使用系統; 使用System.Collections.Generic; 使用System.Linq; 使用System.Text;

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

IL代碼

.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

正如你在這里看到的那樣,使用block是在try ... finally中轉換的。 但該類必須實現IDispose接口

我不知道除了代碼縮進之外的任何缺點。 顯而易見的是,您不必擔心丟棄物體,因為一旦使用支架留下它們就會被丟棄。

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

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

我認為你的代碼是相當不錯的,但我個人寧願重構一個using子句來分離函數,因為有5個連續的花括號(即})會使代碼不易讀取。 但這是我的觀點 - 我喜歡盡可能降低壓痕水平。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM