代码分析CA1063在从IDisposable派生并在基类中提供实现时触发

本文关键字:实现 基类 CA1063 在从 IDisposable 派生 代码 | 更新日期: 2023-09-27 18:20:52

我有一些代码会触发代码分析警告CA1063:

CA1063:Microsoft.Design:从"Functionality"实现的接口列表中删除IDisposable,并重写基类Dispose实现。

但是,我不确定我需要做些什么来修复这个警告。

简单地说,我有一个从IDisposable派生的接口IFunctionality。类Functionality实现IFunctionality,但从类Reusable派生以能够重用som代码。类Reusable也是从IDisposable派生而来的。

public class Reusable : IDisposable {
  ~Reusable() {
    Dispose(false);
  }
  public void Dispose() {
    Dispose(true);
    GC.SuppressFinalize(this);
  }
  protected virtual void Dispose(Boolean disposing) {
    // ...
  }
  public void DoSomething() {
    // ...
  }
}
public interface IFunctionality : IDisposable {
  void DoSomething();
  void DoSomethingElse();
}
public class Functionality : Reusable, IFunctionality {
  public void DoSomethingElse() {
    // ...
  }
#if WORK_AROUND_CA1063
  // Removes CA1063
  protected override void Dispose(Boolean disposing) {
    base.Dispose(disposing);
  }
#endif
}

我可以通过在Functionality上重写Dispose并调用基类Dispose来消除警告,尽管这样做不会改变代码的语义。

那么,在这种情况下,IDisposable是否有我忽略的地方,或者只是CA1063不适合这种特定的结构?

我知道我可以抑制CA1063,但规则非常宽泛,我不想错过该规则报告的IDisposable在实现中的任何其他问题。

代码分析CA1063在从IDisposable派生并在基类中提供实现时触发

这是一个误报,因为规则本身存在一个小错误。当试图弄清楚一个类是否重新实现IDisposable时(在弄清楚有一个基类实现可以被重写之后),它只看类的接口是否包括IDisposaable。不幸的是,程序集元数据中显示的接口列表包括接口的"分解"列表,包括通过类在原始C#代码中显式实现的接口继承的任何接口。这意味着FxCop看到的Functionality类声明如下:

public class Functionality : Reusable, IFunctionality, IDisposable
{
    ...
}

给定此元数据表示,ImplementIDisposableCorrectly规则应该更智能地判断类是否真的在重新实现IDisposable(例如,如果基类具有可重写的Dispose(bool),则通过查找显式Dispose()实现)。然而,考虑到规则没有做到这一点,你最好的方法是抑制误报。

顺便说一句,我建议认真考虑使用SuppressMessageAttribute来抑制误报,而不是使用当前的条件编译方法。例如:

[SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly",
    Justification = "False positive.  IDisposable is inherited via IFunctionality.  See http://stackoverflow.com/questions/8925925/code-analysis-ca1063-fires-when-deriving-from-idisposable-and-providing-implemen for details.")]
public class Functionality : Reusable, IFunctionality
{
    ...
}

此外,你可能需要认真考虑摆脱终结器。。。

对于再次实现IDisposable的派生类,您的"变通方法"是正确的模式。

但我认为你应该重新考虑IFunctionality : IDisposable的设计。一次性使用真的是IFunctionality关注的问题吗?我认为这个决定属于实现类。

这与IDisposable的使用有关,而不是与接口本身有关。您只是通过提供和重写受保护的Dispose(bool)方法来实现推荐的模式,而不是接口本身的一部分。

如果你的覆盖方法实际上没有添加任何内容,那么省略它是没有问题的。警告CA1063是为了向你强调这个问题,但如果你知道在你的情况下实际上没有资源可供处理,那么你可以通过提供空的实现或排除这个特定文件的这个特定规则来绕过它。

可以使用[SuppressMessage]属性执行此操作。