.NET IDisposable内联临时值

时间:2009-12-08 16:25:34

标签: .net idisposable

我使用代码抢购和重构专业版(突出显示可能的代码问题,像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不感兴趣,我知道有些东西实现它并且它并不是真正需要的(尽管应该总是这样做)。如果它被调用,我特别感兴趣。

4 个答案:

答案 0 :(得分: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();
}

答案 1 :(得分:1)

在超出范围的对象上不会自动调用

Dispose() - 您需要在StudentQueriesTableAdapter中包含对using() {...}的引用,以便正确处理它。

另一个选择是合并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而不执行任何操作,但您应该 始终 using中的任何IDisposable对象包装起来 - 它是使用该类的合同的一部分,否则您可能最终泄漏资源(例如,如果以后的版本中将填写一个空的Dispose方法)

答案 2 :(得分:1)

虽然规范的一部分是让一个项目实现IDisposable有一个终结器来执行该调用,如果它没有在之前执行,这是一个糟糕的坏习惯 。如果您实例化一个实现IDisposable并已完成的对象,则调用Dispose

答案 3 :(得分:1)

仅在实现使用using块的IDisposable()的对象上调用Dispose。

由于