6

我今天在写一些IDisposable代码时正在考虑这个问题。

开发人员最好Dispose()直接调用,或者如果对象的生命周期允许,使用using构造。

我们需要担心的唯一实例是那些using由于代码机制而无法使用的实例。但我们应该在某个时候调用Dispose()这些对象。

鉴于 C# 编译器知道一个对象 implements IDisposable,理论上它也可以知道它Dispose()从未被调用过(它是一个非常聪明的编译器!)。它可能不知道程序员何时应该这样做的语义,但它可以很好地提醒它永远不会调用,因为它从未在using构造中使用过,并且Dispose()从未在任何实现的对象上直接调用该方法IDisposable.

这有什么原因,还是有想法走这条路?

4

3 回答 3

2

它理论上也可以知道它Dispose()从未被调用过

它可以确定在某些简单的情况下Dispose永远不会被调用。仅基于对代码的静态分析,无法确定所有创建的实例都将被处理掉。代码也不需要非常复杂,即使估计对象是否未被处理也很简单。

更糟糕的是,并非所有IDisposable对象实例都应该被释放。这可能有很多原因。有时,IDisposable即使对象的一部分实例实际上在实现中做任何事情,对象也会实现。(IEnumerator<T>就是一个很好的例子。大量的实现在处理时什么都不做,但有些会做。如果你知道具体的实现是什么,你就不会在处理时做任何事情;如果你不知道你需要确保你打电话Dispose

还有一些类型,例如Task几乎从不需要处理的类型。(请参阅我需要处置任务吗?。)在绝大多数情况下,您不需要处置它们,并且不必要地用using块或处置调用来混乱您的代码,这些调用不会妨碍可读性。

于 2013-04-17T19:51:39.003 回答
2

主要规则IDisposable是“最后一个离开房间的人,请关灯”。大多数 .NET 语言的设计中的一个主要失败是没有通用句法(甚至属性标记)约定来指示包含特定变量或包含特定字段的类的代码是否将:

  1. 永远是最后一个离开房间的人
  2. 永远不要成为最后一个离开房间的人
  3. 有时是最后一个离开房间的人,并且在运行时很容易知道它是否会离开(例如,因为谁给了它一个参考告诉它)。
  4. 可能是最后一个离开房间的人,但在它离开房间之前不知道它是否会是最后一个离开的人。

如果语言有语法来区分这些情况,那么编译器很容易确保知道它们将是最后一个离开房间的东西会关掉灯和永远不会的东西最后一个离开房间的人不要关灯。如果框架包含编译器知道的包装器类型,则编译器或框架可以促进第三种和第四种情况。传统的引用计数通常不能作为确定何时不再需要对象的主要机制,因为每次复制或销毁引用时它都需要处理器互锁,即使副本的持有者知道它不会是“最后一个离开房间”,

在没有约定是否应将特定引用视为“房间中的最后一个”的情况下,编译器无法知道该引用的持有者是否应该“关灯”(即 call Dispose) . VB.NET 和 C# 对于一种特殊情况都有特殊的using语法,其中变量的持有者知道它将是最后一个离开房间的人,但除此之外,如果编译器不这样做,编译器就不能真正要求清理这些东西。不明白他们。C++/CLI 确实有更通用的语法,但不幸的是它在使用上有很多限制。

于 2013-04-18T15:14:49.227 回答
1

代码分析规则将检测到这一点。根据您的 VS 版本,您可以使用 FXCop 或内置分析规则。

它需要在编译后对代码进行静态分析。

于 2013-04-17T19:32:53.980 回答