具有一次性场地的类应该是一次性的

时间:2017-04-07 10:41:50

标签: c# fxcop

FxCop警告"带有一次性领域的课程应该是一次性的"有时会让我困惑。见下面的设计示例

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

问题是

  1. 制作只借用一次性资源的课程是反模式。可以将一次性资源作为方法参数传递给Util1和Util2,问题就会消失。只有创建一次性资源的类应该将它们作为字段,因此字段本身就是表示所有权的。

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

  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 */ }
    }
    

1 个答案:

答案 0 :(得分:2)

在大多数情况下,如果你有一个一次性领域,这意味着你想在以后使用它并包装它。如果将此字段返回到外部代码,除非您能够在每次使用之前检查资源是否已处理,否则可以将其置于中断并打破您自己的类。

如果您只想制作布料,则不需要将可处置资源保留为字段。 这就是为什么这个规则经常是正确的,但在一些特殊的罕见情况下,你可以做出一个“不会解决的问题”。

其他模式非常罕见,因为在不引入错误的情况下很难维护。