【发布时间】:2011-01-02 02:39:00
【问题描述】:
可能重复:
Should I Dispose() DataSet and DataTable?OP 评论:我想说“我应该 Dispose() DataSet 和 DataTable 吗?”链接不是一个可能的解决方案。这是一个很好的链接,但这与设计有关。相反,请忽略公开的属性是 DataSet 并将其替换为应处置的内容。同样的问题也适用于那里。
我在搞乱水晶报表,我有一个“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,你最好 Dispose 它。一个DataSet实现了IDisposable,所以我们需要Dispose它。
这里是设计部分的用武之地:
问题 1a:我是否将 ReportData 类设为 IDisposable?
换句话说,看起来我可以这样做并完成它:
private void SetReportDataSource()
{
using (DataSet1 ds = m_RptData.GetDataSet)
{
m_Rpt.SetDataSource(ds);
}
}
问题 1b:我是否应该在某种程度上更具防御性?
我不知道,我想我真的,真的在努力确保它得到处理。例如,以我的 SetReportDatsSource 函数为例。我使用了“using”,但其他人可能会使用该类而忘记添加 using 或以某种方式调用 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 中那样使用“using”),你开始考虑让这个调用类 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 之间,可能会发生一些错误/异常。因此,我们永远没有机会对我们的数据集进行“使用”(在 SetReportDataSource 内部)。但是那个数据集是用 ReportData 构建的(我们想在它上面调用 dispose!)
所以,现在我们回到制作 ReportData IDisposable 的过程中,因为我们至少需要一些公共的“CleanUp”功能......好吧,我完成了。 :)
【问题讨论】:
-
我想说“我应该 Dispose() DataSet 和 DataTable 吗?”链接不是一个可能的解决方案。这是一个很好的链接,但这与设计有关。相反,请忽略暴露的属性是一个 DataSet 并将其替换为应该被释放的东西。
-
有人投票将其关闭为“公然冒犯”?埃加德。
-
也许这与你争论的语气和你荒谬的标题有关?你那长得不值一提的帖子怎么样?您在帖子中使用的格式缺失或可笑的表情如何?我想知道为什么有人不会觉得这令人反感。
-
@Chet A - 我不道歉;它们略有不同(您会注意到关闭它的也是我,以添加交叉引用)
-
@JustLooking - 你在这里问了一些非常冗长的问题,这让人们很难理解。我认为,如果您可以使问题更...具体,您将获得更多有用的答案。