类带一次性字段应该是一次性的

Classes with disposable fields should be disposable

FxCop 警告 "Classes with disposable fields should be disposable" 有时让我感到困惑。请参阅下面的人为示例

只有一种类型创建拥有一次性资源,但任意数量的类型都可以使用(或"borrow")这个资源。我看到开发人员在 Util1 和 Util2 上发出 FxCop 警告,表明由于他们有一个一次性类型的字段,他们必须实施 Dispose 并处置该字段。这显然不是你想要的。

问题是

  1. 使 classes 只借用一次性资源是一种反模式。一次性资源可以作为方法参数传递给 Util1 和 Util2,问题就会消失。只有 classes create 一次性资源应该将它们作为字段,以便字段本身就是所有权的指示。

  2. 警告不够聪明。当 拥有 一次性资源的类型本身不是一次性资源时应该发出警告,在这种情况下只有一个 class 拥有它,而其他人借用它。它仅从构造函数参数注入的事实本可以被更聪明的规则用来检测不应为借用 class.

  3. 引发警告
  4. 还有别的吗?

static class Program
{
   public static void Main() 
   {
      using(var r = new SomeResource()) 
      {
          Console.WriteLine(new Util1(r).Foo());   
          Console.WriteLine(new Util2(r).Foo());   
      }                                 
   }
}

public sealed class SomeResource : IDisposable 
{
   private readonly NativeResource native;
   public void SomeResource() 
   {
      native = Native.CreateDisposableThing();
   }
   public void Dispose()
   {
      native.Dispose();
   }
}

public sealed class Util1 {
   private readonly SomeResource res;
   public Util1(SomeResource res) {  this.res = res; }
   public string Foo() { /* uses res */ }
}

public sealed class Util2 {
   private readonly SomeResource res;
   public Util2(SomeResource res) {  this.res = res; }
   public string Foo() { /* uses res */ }
}

在大多数情况下,如果你有一个一次性字段,这意味着你想稍后使用它并包装它。如果您 return 此字段到外部代码,它可以被释放并破坏您自己的 class 除非您能够在每次使用前检查资源是否被释放。

如果你只是想做一个面料,你不需要把一次性资源作为田地。 这就是为什么这个规则通常是正确的,但在一些特殊的罕见情况下,你可以做出 "won't fix".

其他模式很少见,因为很难在不引入错误的情况下进行维护。