可能重复:
Should I Dispose() DataSet and DataTable?OP评论:我想说“我应该Dispose()DataSet和DataTable吗?”链接不是一个可能的解决方案。这是一个很好的链接,但这与设计有关。相反,忽略exposed属性是一个DataSet,并用应该处理的东西替换它。同样的问题也适用于那里。
我正在搞乱Crystal Reports,我有一个“ReportData”类。换句话说,这个类封装了我将使用的DataSet的“填充”。
public class ReportData
{
private DataSet1 m_DS = null; // Notice this disposable member variable
public ReportData( ... some parameters ...)
{
m_DS = new DataSet1();
// Plus some other manipulation on m_DS
}
public DataSet1 GetDataSet
{
get
{
return m_DS;
}
}
// Everything else is pretty much private.
// This class is here to generate my DataSet
}
以下是其他一些课程的使用方法:
private void SetReportDataSource()
{
DataSet1 ds = m_RptData.GetDataSet;
m_Rpt.SetDataSource(ds);
}
我几乎在学习C#(在一本介绍书中阅读几章,然后继续阅读,一路上搜索所有内容)。据我所知,如果它实现了IDisposable,你最好配置它。 DataSet实现了IDisposable,因此我们需要Dispose它。
这是设计部分的用武之地:
问题1a:我是否将ReportData类设为IDisposable?
换句话说,看起来我可以这样做并完成它:
private void SetReportDataSource()
{
using (DataSet1 ds = m_RptData.GetDataSet)
{
m_Rpt.SetDataSource(ds);
}
}
问题1b:我是否应该以某种方式更具防御性?
我不知道,我想我真的,真的想确保它被处理掉。例如,以我的SetReportDatsSource函数为例。我使用“使用”,但其他人可能会使用该类而忘记添加使用或以某种方式调用Dispose。因此,我转到我的ReportData类:
public class ReportData : IDisposable
{
private DataSet1 m_DS = null; // Notice this disposable member variable
private bool m_IsDisposed = false; // This is new!
public ReportData( ... some parameters ...)
{
m_DS = new DataSet1();
// Plus some other manipulation on m_DS
}
// New code here (up until the GetDataSet property)
~ReportData()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (m_IsDisposed == true)
{
return;
}
if (m_DS != null)
{
m_DS.Dispose();
m_DS = null;
}
m_IsDisposed = true;
}
// Done with new code
public DataSet1 GetDataSet
{
get
{
return m_DS;
}
}
// Everything else is pretty much private.
// This class is here to generate my DataSet
}
现在,让我们回到调用类,我们仍然有:
private void SetReportDataSource()
{
using (DataSet1 ds = m_RptData.GetDataSet)
{
m_Rpt.SetDataSource(ds);
}
}
但是,我现在也将ReportData(m_RptData)丢弃了!所以,我们要去处理它!因为它是一个成员变量(我不能像我在SetReportDataSource中使用它那样使用“使用”),所以你开始考虑使这个调用类具有IDisposable,所以我可以:
protected virtual void Dispose(bool disposing)
{
if (m_IsDisposed == true)
{
return;
}
if (m_ReportData != null)
{
m_ReportData.Dispose();
m_ReportData = null;
}
m_IsDisposed = true;
}
所以,现在这个类有析构函数/终结符及其公共Dispose方法,处理ReportData。我们保证我们处理DataSet!
但话说再次,这将导致DataSet的Dispose方法被调用两次。因为SetReportDataSource函数处理公开的DataSet,而ReportData类也处理相同的事情(并且没有一种简单的方法来确定是否有人处理了公开的DataSet)。
似乎有点疯狂。在我看来,我:a)可能会过度思考这个(或者只是想要真正的防守,这很好)!
b)可能会跳过一堆篮球。
也许规则应该是:如果我的类要暴露它,那么调用函数应该负责处理它。
我看到的唯一问题(这就是我在这里发布的原因):
在实例化ReportData成员变量和调用SetReportDataSource之间,可能会发生一些错误/异常。所以,我们永远不会有机会在我们的DataSet上进行“使用”(在SetReportDataSource内部)。但是该数据集是使用ReportData构建的(我们想在其上调用dispose!)
所以,现在我们回到制作ReportData IDisposable,因为我们至少需要一些公共的“CleanUp”功能......好吧,我已经完成了。 :)
答案 0 :(得分:4)
如果您持有实现IDisposable的东西,最简单的模式是自己实现IDisposable,并在您拥有的所有IDisposable上调用Dispose方法。更加防守而不是看起来不可行;如果有人使用你的班级忘记来调用你的Dispose方法,那你怎么知道他们是用你做的?
编辑:再想一想,Finalize调用会告诉您,您的客户已经完成了您的使用;他们没有更多的提及你...
答案 1 :(得分:3)
请参阅:Should I Dispose() DataSet and DataTable?
如上所述,如果一个对象实现了IDisposable,那么你应该调用Dispose()。 [在.NET框架中有一些地方原始设计师,可能是他们需要Dispose(),但后来不需要它。但最安全和正确的做法是无论如何都要调用Dispose。]
答案 2 :(得分:1)
您没有显示SetDataSource
的代码,但是这段代码只有在SetDataSource
立即使用DataSet的内容并且不存储对它的引用时才会起作用:
private void SetReportDataSource()
{
using (DataSet1 ds = m_RptData.GetDataSet)
{
m_Rpt.SetDataSource(ds);
}
}
至于你的其余代码和问题(引用已删除的答案):
您没有任何需要最终确定的内容。您可能已经注意到,当您发现您没有使用处置参数时。所有你需要的是:
void Dispose() {
if (m_DS != null) m_DS.Dispose()
}
终结者的一般规则是:如果有疑问,请不要 直接使用非托管资源时,您只需要一个。
答案 3 :(得分:0)
答案1A:我会推荐使用语法,原因是它似乎是处理这种性质的标准。
答案1B:如果其他人正在使用您的课程,我认为您的意思是延伸,实施者可以处理他认为合适的任何更改。根据Dispose()上的文档
如果多次调用对象的Dispose方法,则该对象必须忽略第一个之后的所有调用。如果多次调用Dispose方法,则该对象不得抛出异常。如果发生错误,Dispose可以抛出异常,因为资源已经被释放,并且之前没有调用Dispose。 (http://msdn.microsoft.com/en-us/library/system.idisposable.dispose%28VS.71%29.aspx)
垃圾收集器会在某个时刻抓住您的对象并处理它。除非发生灾难。