2009-12-08 13 views
0

我使用代碼繁忙和重構專家(突出可能的代碼問題,如ReSharper等),他們告訴我,我有未置備的當地人(實施IDisposable)。所以,我有兩個using語句改變了代碼這樣:.NET IDisposable行內臨時工

using (Reports.StudentRegisters.StudentQueriesDataTable studentDataTable = new Reports.StudentRegisters.StudentQueriesDataTable()) 
     { 
      using (StudentQueriesTableAdapter studentTableAdapter = new StudentQueriesTableAdapter()) 
      { 
       try 
       { 
        studentTableAdapter.FillByQAbsenceRegRow(studentDataTable, year, school, division, progArea, sinceWeek, missedLessons, includeWdlTrn, ageMin, ageMax, studentGLH); 
        ds = new DataSet(); 
        ds.Tables.Add((DataTable)studentDataTable); 
        ReportDocument.SetDataSource(ds.Tables[0]); 
       } 
       catch (Exception err) 
       { 
        LogReportError(err, this.CrystalViewer, null, ErrorType.Reporting); 
       } 
      } 
     } 

由於studentTableAdapter使用一次我能線它象下面這樣:

using (Reports.StudentRegisters.StudentQueriesDataTable studentDataTable = new Reports.StudentRegisters.StudentQueriesDataTable()) 
     { 
       try 
       { 
        (new StudentQueriesTableAdapter()).FillByQAbsenceRegRow(studentDataTable, year, school, division, progArea, sinceWeek, missedLessons, includeWdlTrn, ageMin, ageMax, studentGLH); 
        ds = new DataSet(); 
        ds.Tables.Add((DataTable)studentDataTable); 
        ReportDocument.SetDataSource(ds.Tables[0]); 
       } 
       catch (Exception err) 
       { 
        LogReportError(err, this.CrystalViewer, null, ErrorType.Reporting); 
       } 
     } 

顯然,在這種解決方案我現在也沒辦法調用處理StudentQueriesTableAdapter。這是否被自動調用,因爲沒有對對象的引用,或者這可能會導致某些處理不當。

我會強調我對我是否真的需要在兩個對象上使用dispose並不感興趣,我知道有些東西實現它並且它不是真的需要(儘管應該總是這樣做)。如果它被調用,我特別感興趣。

回答

4

不,它不會被調用。 Using(foo){ DoSomething() }爲(大約)在功能上等同於:

var objectToDispose = foo as IDisposable; 
try 
{ 
    DoSomething(); 
} 
finally 
{ 
    if(objectToDispose != null) 
     objectToDispose.Dispose(); 
} 

正因爲如此,你的StudentQueriesTableAdapter沒有得到安置。

我常常儘量減少與多個處置這樣的嵌套:

using (var foo = new Foo()) 
using (var bar = new Bar(foo)) 
{ 
    DoSomething(); 
} 
+0

我喜歡你的雙倍使用技術,使它看起來更整潔。嵌套是我不喜歡我原來的代碼佈局的主要原因。 – PeteT 2009-12-08 20:32:57

+0

是的,這是用嵌套'使用'塊來避免額外縮進的慣用方法。 – 2009-12-08 20:33:36

1

Dispose()不會在超出範圍的對象上自動調用 - 您需要在using() {...}中包含對StudentQueriesTableAdapter的引用,以使其正確放置。

另一種選擇是將usingtry,結合以降低多少有點築巢:

using (Reports.StudentRegisters.StudentQueriesDataTable studentDataTable = new Reports.StudentRegisters.StudentQueriesDataTable()) 
    { 
     StudentQueriesTableAdapter studentTableAdapter; 

     try 
     { 
      studentTableAdapter = new StudentQueriesTableAdapter(); 
      studentTableAdapter.FillByQAbsenceRegRow(studentDataTable, year, school, division, progArea, sinceWeek, missedLessons, includeWdlTrn, ageMin, ageMax, studentGLH); 
      ds = new DataSet(); 
      ds.Tables.Add((DataTable)studentDataTable); 
      ReportDocument.SetDataSource(ds.Tables[0]); 
     } 
     catch (Exception err) 
     { 
      LogReportError(err, this.CrystalViewer, null, ErrorType.Reporting); 
     } 
     finally 
     { 
      if (studentTableAdapter != null) 
       studentTableAdapter.Dispose(); // or Close(), depending on which method is public 
     } 
    } 

實際上,這就是一個using {}沒有 - 在try/finally從句把它包

需要注意的是,儘管一些對象可以通過Dispose方法實現IDisposable而不做任何事情,但您應該總是使用將任何IDisposable對象包含在using中 - 它是公司的一部分如果在未來的版本中填寫空的Dispose方法)

1

雖然它是規範的一部分,但要有一個實現IDisposable的項目才能具有終結器如果之前未執行該呼叫,則執行該呼叫,這是壞的,壞習慣。如果您實例化一個實現了IDisposable的對象並完成它,請致電Dispose

+0

什麼規範的一部分?當我實現IDisposable時,我通常在終結器中執行Debug.Assert(false),只是爲了確保如果我忘記處理某些東西,我會盡快學會。 – erikkallen 2009-12-08 16:46:38

+0

@erik:請參閱http://msdn.microsoft.com/en-us/library/system.idisposable。aspx獲取更多信息。如果您設計了一個'IDisposable'組件/類,則應該始終實現釋放*非託管*資源(但不包含託管資源)的終結器。這是'Dispose(bool disposing)'重載的模式,'Dispose()'傳遞'true'並且終結器傳遞'false'。 – 2009-12-08 16:52:29

+0

我認爲這更多的是建議的實現,而不是規範的一部分。 – erikkallen 2009-12-08 17:32:03

1

僅在實現IDisposable()的對象上調用Dispose,該對象使用using塊。

謝謝