我使用代码抢购和重构专业版(突出显示可能的代码问题,像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不感兴趣,我知道有些东西实现它并且它并不是真正需要的(尽管应该总是这样做)。如果它被调用,我特别感兴趣。
答案 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() {...}
的引用,以便正确处理它。
另一个选择是合并using
和try
,以减少嵌套:
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。
由于