Подтвердить что ты не робот

Анализ кода CA1063 срабатывает при получении из IDisposable и обеспечения реализации в базовом классе

У меня есть код, который вызовет предупреждение анализа кода CA1063:

CA1063: Microsoft.Design: Удалите IDisposable из списка интерфейсов, реализованных с помощью функции "Функциональность", и переопределите базовый класс. Вместо этого удалите реализацию.

Однако я не уверен, что мне нужно сделать, чтобы исправить это предупреждение.

Вкратце, у меня есть интерфейс 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, описанных в этом правиле.

4b9b3361

Ответ 1

Это ложное позитивное из-за незначительной ошибки в самом правиле. При попытке выяснить, переопределяет ли класс IDisposable (выяснив, что существует реализация базового класса, которую можно переопределить), он рассматривает только, включают ли интерфейсы класса IDisposable. К сожалению, список интерфейсов, отображаемый в метаданных сборки, включает в себя "взорванный" список интерфейсов, включая любые интерфейсы, унаследованные через интерфейсы, которые класс явно реализует в исходном коде С#. Это означает, что FxCop видит для класса Functionality следующее:

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

Учитывая это представление метаданных, правило ImplementIDisposableCorrectly должно быть немного более интеллектуальным в том, как он пытается определить, действительно ли класс действительно повторно реализует IDisposable (например, ищет явную реализацию Dispose(), если базовый класс имеет overrideable Dispose (bool)). Однако, учитывая, что правило не делает этого, ваш лучший подход заключается в подавлении ложных срабатываний.

Кстати, я бы порекомендовал серьезно рассмотреть возможность использования 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
{
    ...
}

Кроме того, вы можете серьезно подумать о об избавлении от финализатора...

Ответ 2

Ваше "обходное решение" - это правильный шаблон здесь, для производного класса, который снова реализует IDisposable.

Но я думаю, вы должны пересмотреть дизайн IFunctionality : IDisposable. Является ли "Одноразовая" действительно проблемой IFunctionality? Я думаю, что это решение принадлежит классу-исполнителю.

Ответ 3

Это связано с использованием IDisposable, а не с самим интерфейсом. Вы просто применяете рекомендуемый шаблон для его использования, предоставляя и переопределяя защищенный метод Dispose(bool) - это не часть самого интерфейса.

Если ваш метод переопределения фактически ничего не добавляет, тогда нет проблем с его отсутствием. Предупреждение. CA1063 должен подчеркнуть эту проблему, но если вы знаете, что в вашем случае нет ресурсов для размещения в вашем случае, вы можете обойти это, либо предоставив пустую реализацию, либо вы исключив это конкретное правило для этого конкретного файл.

Вы можете сделать это с помощью атрибута [SuppressMessage].