处理嵌套的一次性物品?

时间:2010-07-22 06:19:29

标签: c# .net dispose idisposable

我想知道是否有关于处理嵌套在另一个一次性物品内的一次性物品的约定(在财产/公共领域,而不是私人成员)。例如,DataSet包含DataTable,而SqlCommand包含SqlConnection。

显而易见的是,一个班级可以处理它拥有的所有Disposable物品,剩下的就是其余部分。是否存在这样的惯例?如果是这样,.NET库如何确定谁拥有什么?如何确定是否正在处理嵌套对象?

PS:我一直在想这个问题,其他人显然也是这样:What gets disposed when SqlCommand.Dispose is called?

编辑1:发现配置DataSet,不配置其表。

// Fill dataset from sqldataadpater.
foreach (DataTable dt in dataSet.Tables)
{
    dt.Disposed += Program.DisposedEventHandler2;
}
Console.WriteLine("Disposing dataset");
dataSet.Dispose(); //Event not fired here.
Console.WriteLine("Disposing datatables maually");
foreach (DataTable dt in dataSet.Tables)
{
    dt.Dispose(); //Event fired here
}
#endregion

3 个答案:

答案 0 :(得分:7)

我通常遵循的经验法则是创建一次性物体的类也将处置它。例如:SqlCommand不会释放它的连接,因为它没有创建它。 StreamReader在这个意义上有一个奇怪的行为,因为它总是处理底层流,即使它是从外部提供的(我发现这很烦人,当你喜欢微软时,请投票HERE解决这个问题)。

答案 1 :(得分:3)

我会说通常一个容器将处置任何包含的一次性项目 - StreamReader处理底层流,例如 - 但通常我将使用单独的{处理每个项目{无论如何{1}}声明。

任何“所有权”的概念实际上只是在文档和惯例中。基本上你必须知道什么会处理什么,这通常意味着阅读文档并希望它清楚地说明。不幸的是,它并不总是如此:(

请注意,这里没有单一的正确答案 - 有时您可能希望某种类型的行为方式,有时则需要另一种方式。有些类型明确允许您说明您是否有效地转移了资源的所有权,尽管大多数都没有。

答案 2 :(得分:0)

最好的方法通常是为嵌套的IDisposable项提供一个指示,指示嵌套项是否应与容器一起处理,除非项的使用寿命永远不会超过容器的使用寿命(在这种情况下处理容器)可以处置物品),或者可以确定除了容器之外的最后一个实体需要包含的物品将意识到它的存在和需要处置(意味着容器不必担心处置,因为另一个item可以处理它。)

作为一个简单的例子,假设有人正在设计一个UI框架,并希望提供一个应该显示Picture的控件,并提供一种代码可以提供要显示的图像的方法。进一步假设某些类型的Picture具有需要处理的资源。在某些情况下,代码可能希望在多个控件上显示某个Picture,这些控件可能并非全部同时处理。在这种情况下,如果处置一个控件来处理它的图片就不好了。另一方面,在其他情况下,代码可能会为了显示而创建图片,将其提供给控件,然后不再关心它。在这种情况下,提供图片的代码可能知道图片应该在控件不再需要时处理,但可能不知道何时会发生。

使用参数指示图片是否应为Disposed将允许在上述两种情况下都使用干净的代码。另一种方法是Winforms使用的方法,即在控件的图片更改或更改Image属性时发生事件。将控件的Image属性设置为需要处理的图像的代码可以使用这些事件来处理它。