2010-07-22 67 views
4

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

显而易见的情况是,一个班级会处理它拥有的所有一次性物品,剩下的部分将会丢弃。是否存在这样的约定?如果是这样,.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 

回答

7

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

+0

有时候它很烦人,这意味着你可以使用'新的StreamReader(新的FileStream(...))'而不必担心有两个'使用'语句......通常可以提高可读性,国际海事组织。 – 2010-07-22 06:36:24

+0

@Jon:我明白为什么BCL团队选择这个API设计。它指导.NET开发人员“成功的基石”(就像Rico Mariani所说的那样)。但是,我错过了重载的枚举或布尔标志,命令'StreamReader'使流保持活着。在当前的设计中,使流保持活动状态意味着您将不得不使用'class DoNotDisposeStreamDecorator:Stream'封装流。 – Steven 2010-07-22 06:46:34

+0

是的,我自己就有这样一个装饰器... – 2010-07-22 07:21:49

3

我要说的是通常容器将处理任何包含一次性项目 - 底层流的StreamReader处置,例如 - 但通常我会用一个单独的using声明反正处置各项目。

“所有权”的任何概念都只是在文档和约定中。基本上你必须知道什么会处理什么,这通常意味着阅读文档并希望它清楚。不幸的是,它并不总是这样做:(

请注意,这里没有单一的正确答案 - 有时您可能希望某种类型的行为是单向的,有时是另一种行为。有些类型显式允许您声明自己是否有效地转移资源的所有权,虽然大多数不是。

+0

但是,当我使用一个数据集,例如,我使用查询读取,我希望处置数据表(和数据表包含datacolumns等...)它包含手动?我真的想不出一个优雅的方式来做到这一点。 – apoorv020 2010-07-22 06:29:34

+0

我最担心的是BCL库,因为他们的处理方法没有文档,我使用它们很多。 – apoorv020 2010-07-22 06:31:55

+0

@ apoorv020:'DataTable'和'DataSet'在某种程度上是古怪的。除非您使用远程处理,否则根据我的意识,您不需要处理它们。他们真的只是一次性的,因为他们是远远不够的。它们继承了MarshalByValueComponent的可处置性。 – 2010-07-22 06:32:49

0

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

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

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