【问题标题】:Classes with disposable fields should be disposable具有一次性字段的类应该是一次性的
【发布时间】:2017-04-07 10:41:50
【问题描述】:

FxCop 警告“具有一次性字段的类应该是一次性的”有时让我感到困惑。请参阅下面的人为示例

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

有问题吗

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

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

  3. 还有别的吗?

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

【问题讨论】:

  • 嗯,这只是静态分析,它可能是对的,也可能是错误的。它无法知道您是否拥有或借用该资源,因此如果您知道自己在做什么 - 只需针对这种特殊情况禁用此警告。从您提供的选项来看,我认为 2 是正确的。
  • 我猜是#2
  • 我也相当确定它是 #2,但考虑到制定规则似乎很容易,至少忽略 IDisposable 注入到 ctor 的类型,我真的很好奇它是否还有更多内容。

标签: c# fxcop


【解决方案1】:

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

如果您只想制作面料,则无需将可处置资源保留为字段。 这就是为什么这条规则通常是正确的,但在一些特殊的罕见情况下,你可以做出“不会修复”。

其他模式非常少见,因为如果不引入错误就很难维护。

【讨论】:

  • 谢谢。这是 1 和 2 的一种。我想对上述情况的一个很好的解决方案是使该字段成为 Util 中的参数(解决方案 1)使这些实用程序成为私有类,以便它们可以t 比所有者长寿。关于借用者永远无法确定他的资源是否还活着的观点是一个很好的论点 - 一个让资源成为 Util 中所有方法的参数的论据。
  • @AndersForsgren 借用模式一直在发生,而且并不罕见。以任何 asp.net 应用程序为例。数据库连接(或实体框架上下文)在构造函数中的任何地方都被注入,但它的生命周期由外部管理,注入它的类不负责处理它。
  • 如果您信任您的消费者,强制其尊重文档或进行代码分析以完成它们,则认为某些模式是可以接受的。在其他情况下,这只是您是否愿意承担的风险。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多