.NET IDisposable内联temp

.NET IDisposable内联temp,.net,idisposable,.net,Idisposable,我使用code rush和refactor pro突出可能的代码问题,比如ReSharper,他们告诉我我有未经分解的局部变量,实现了IDisposable。因此,我使用两个using语句将代码更改为: using (Reports.StudentRegisters.StudentQueriesDataTable studentDataTable = new Reports.StudentRegisters.StudentQueriesDataTable()) {

我使用code rush和refactor pro突出可能的代码问题,比如ReSharper,他们告诉我我有未经分解的局部变量,实现了IDisposable。因此,我使用两个using语句将代码更改为:

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。这是自动调用的,因为不再有对对象的引用,或者这可能会导致某些内容无法正确处理

我要强调的是,我对是否真的需要在这两个对象上使用dispose不感兴趣,我知道有些东西可以实现它,虽然应该总是这样做,但实际上并不需要。我特别感兴趣的是它是否被调用。

对于超出范围的对象不会自动调用Dispose-您需要在using{…}中包装对StudentQueriesTableAdapter的引用,以便正确地对其进行处理

另一种选择是结合使用和尝试,稍微减少嵌套:

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方法,而规范的一部分是有一个实现IDisposable的项,如果之前没有执行该调用,则有一个执行该调用的终结器,这是一个坏习惯。如果实例化了一个实现IDisposable的对象并完成了它,请调用Dispose

Dispose仅在实现IDisposable的对象上调用,而IDisposable是使用block-on来实现的


谢谢

不,它不会被呼叫。使用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();
}

什么规格的一部分?在实现IDisposable时,我通常在终结器中执行Debug.Assertfalse,以确保在忘记处理某些内容时尽快了解。@erik:有关详细信息,请参阅。如果设计IDisposable组件/类,则应始终实现释放非托管资源但不释放托管资源的终结器。这是一个处理BooBoL处理超载的模式,处理的传递是真的,终结器传递的是假的。我认为这是一个建议的实现,而不是规范的一部分。@埃里克:你当然有权接受你的意见:它是编码风格的一个重要部分。因为如果有人想从实现IDisposable的类中派生一个类,他会期望该模式,如果您不提供该模式,那么您也会强迫他做出选择,因为如果基类不以这种方式实现它,他就无法正确地实现它。同样,C++/CLI ref类析构函数/终结器也使用此模式组合在一起。总之,遵循它肯定会更好,顺便说一句,这并不妨碍你在终结器中添加断言。我喜欢你的双重使用技术,它让我看起来更整洁。嵌套是我不喜欢原始代码布局的主要原因。是的,这是使用块格式化嵌套以避免额外缩进的惯用方法。