3

今天早些时候,我在对工作中的一些代码进行代码分析时遇到了CA1063 。

我有两个问题:

  1. 为什么下面的代码即使明显违反了一些要求也不会导致CA1063(例如Dispose被覆盖)

  2. 导致具有由密封的 Dispose() 和终结器等调用的虚拟 Dispose(bool) 的复杂方案的代码的实际问题是什么......

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
  class Foobar : IDisposable
  {
    public Foobar()
    {
      Console.Out.WriteLine("Constructor of Foobar");
    }

    public virtual void Dispose()
    {
      Console.Out.WriteLine("Dispose of Foobar");
      GC.SuppressFinalize(this);
    }

    ~Foobar()
    {
      Console.Out.WriteLine("Finalizer of Foobar");
    }
  }

  class Derived : Foobar
  {
    public Derived()
    {
      Console.Out.WriteLine("Constructor of Derived");
    }

    public override void Dispose()
    {
      Console.Out.WriteLine("Dispose of Derived");
      GC.SuppressFinalize(this);
      base.Dispose();
    }

    ~Derived()
    {
      Console.Out.WriteLine("Finalizer of Derived");
    }
  }

  class Program
  {
    static void Main()
    {
      Console.Out.WriteLine("Start");
      using (var foo = new Derived())
      {
        Console.Out.WriteLine("...");
      }
      Console.Out.WriteLine("End");
    }
  }
}
4

1 回答 1

5

最初,Microsoft 期望许多类型的对象将同时封装托管和非托管资源,并且即使特定的可继承类没有封装任何非托管资源,派生自它的类也可能会这样做。尽管这种想法在很大程度上是错误的(通常最好将非托管资源分离到它们自己的对象中,然后将其用作托管资源),但旨在处理任意混合的托管和非托管资源的模式成为了一个既定的先例.

尽管完整的 Dispose 模式的某些部分很愚蠢,但适当的简化不会遗漏很多内容。清理代码应该在一个受保护的虚方法中,以允许派生类添加自己的逻辑,但仍然链接到父类方法;如果该方法被命名为Dispose,它必须具有与无参数Dispose方法不同的签名[尽管我自己的偏好是具有不同名称的无参数方法]。我对微软模式最大的抱怨是它要求每个派生类都有自己的逻辑来防止重复处理。让基类在非虚拟Dispose实现中处理它会更干净。

于 2013-03-11T21:06:52.233 回答