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

时间:2012-01-19 12:20:41

标签: c# code-analysis idisposable

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

  

CA1063:Microsoft.Design:从“功能”实现的接口列表中删除IDisposable,改为覆盖基类Dispose实现。

但是,我不确定我需要做些什么才能修复此警告。

简而言之,我有一个IFunctionality派生的界面IDisposable。类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

}

我可以通过在Dispose上覆盖Functionality并调用基类Dispose来消除警告,即使这样做不应该改变代码的语义。

在这种情况下,我忽略了IDisposable还有一些问题,或者只是CA1063对这个特定构造失败了吗?

我知道我可以压制CA1063,但规则相当广泛,我不想错过实施此规则报告的IDisposable中的任何其他问题。

3 个答案:

答案 0 :(得分:39)

由于规则本身存在小错误,这是误报。当试图弄清楚一个类是否重新实现了IDisposable时(在弄清楚有一个可以被覆盖的基类实现之后),它只会查看该类的接口是否包含IDisposable。不幸的是,在程序集元数据中显示的接口列表包括“爆炸”的接口列表,包括通过接口继承的任何接口,类在原始C#代码中明确实现。这意味着FxCop会看到一个类似于以下功能类的声明:

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

鉴于此元数据表示,ImplementIDisposableCorrectly规则应该更加智能地了解它如何尝试确定该类是否实际上正在重新实现IDisposable(例如,如果基类具有查找显式的Dispose()实现一个可以覆盖的Dispose(bool))。但是,鉴于该规则没有这样做,您最好的方法是抑制误报。

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

[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
{
    ...
}

另外,您可能需要认真考虑getting rid of the finalizer ...

答案 1 :(得分:4)

对于再次实现IDisposable的派生类,此处的“解决方法”是正确的模式。

但我认为你应该重新考虑IFunctionality : IDisposable的设计。 Disposable真的是IFunctionality的关注点吗?我认为这个决定属于实施阶层。

答案 2 :(得分:1)

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

如果你的覆盖方法实际上没有添加任何东西,那么省略它就没有问题了。警告CA1063是为了向您突出显示该问题,但如果您知道实际上没有资源可以处理您的情况,那么您可以通过提供您的空实现或通过排除此特定规则来绕过它文件。

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