簡體   English   中英

在變量聲明,初始化和非托管內存分配后清理

[英]Cleaning up after variable declaration, initialization and unamanaged memory allocation

在定義變量,為變量分配空間,初始化變量然后正確清理所有內容時,我想請教您有關c#良好編程實踐的建議。

我目前面臨的問題是,我有一個使用非托管API函數的函數,因此也訪問了非托管內存(使用了封送處理)。 我想使函數保持干凈,並在退出之前妥善處理所有內容。 事實是,所有實際工作都在try-catch塊內完成。 這意味着我不能在catch清潔家居或finally塊。

我要做的是聲明所有變量,為它們保留內存並在進入函數后立即對其進行初始化,然后在finally塊中清理所有內容(關閉句柄,釋放內存等)。

一切都很好,但我也想在try塊中完成變量聲明,初始化和內存分配(例如,初始化數組或在內存中分配空間或上帝知道位置時,也會出問題)。 唯一想到的是嵌套兩個try-catch塊。 這樣可以嗎?還是您會提出其他建議?

這是我到目前為止的內容:

//Declare variables, allocate memory, initialize variables.
........
try
{
    //Do actual work - write to file and read from a file in my case
    .........
}
catch (Exception exc)
{
    //Exception handler for file write/read errors
}
finally
{
    //Clean up (release handles, free memory,...)
}

這就是我的想法:

try
{
   //Declare variables, allocate memory, initialize variables.
   ........
   try
   {
       //Do actual work - write to file and read from a file in my case
       .........
   }
   catch (Exception exc)
   {
       //Exception handler for file write/read errors
   }
}
catch (Exception exc_1)
{
    //Exception handler for variable declaration, initialization, memory allocation errors
}
finally
{
    //Clean up (release handles, free memory,...)
}

預先感謝您的所有幫助!

干杯!

您可以實現IDisposable接口以調用Dispose方法。

或作為最佳做法使用塊using

using (var variable = .....)
{

 ...

}

使用塊的特殊性是在處理結束時調用Dispose方法。

例如,如果您使用SqlConnection

var(var connection = new SqlConnection("...."))
{
....

}

僅此代碼就足夠了

鏈接: http//msdn.microsoft.com/fr-fr/library/vstudio/system.idisposable.aspx

鏈接: http : //msdn.microsoft.com/fr-fr/library/yh598w02%28v=vs.80%29.aspx

該方法的問題是變量最終超出了范圍(並捕獲)

    try
    {
        string testString;
    }
    catch (Exception ex)
    {
    }
    finally
    {
        // testString is not in scope
    }

您擔心該聲明可能會引發運行時錯誤嗎?

基於注釋,OP不知道初始化可以與聲明分開。

    List<string>  testLString;        
    try
    {
        testLString = new List<string>();
    }
    catch (Exception ex)
    {
    }
    finally
    {
        testLString = null;
    }

我不同意您對聲明可能引發運行時錯誤的擔心。
它只做聲明。

您可以根據需要嵌套任意數量的try...catch結構。 這是使代碼負責其自身清理的好方法。

也考慮使用僅tryfinally處理總是需要清理的代碼的結構,而不管它是否正常:

try {

  // do something here

  // declare some variable
  try {
    // allocate space for variable
    // do something with that variable
  } fincally {
    // deallocate space for variable
  }

  // do something more here

} catch(Exception ex) {
  // handle the exception here
}

您應該嘗試使用盡可能具體的異常類,並且可以在同一結構中使用不同的類型來捕獲不同的異常:

try {
  // do some i/o
} catch (IOException ex) {
  // here you know that it was actually the i/o that failed
} catch (Exception ex) {
  // here is for catching anything else that might have failed
}

我建議您創建一個單獨的類型,該類型包裝與非托管API的所有通信,管理內存等。它實現IDisposable接口,該接口的實現負責清理所有非托管資源。 如果您使用的是Windows,最簡單的方法是在C ++ / CLI中實現此包裝。

暫無
暫無

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

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