Поделиться через


CA2202: не удаляйте объекты несколько раз

Товар Значение
Идентификатор правила CA2202
Категория Microsoft.Usage
Критическое изменение Не критическое

Причина

Реализация метода содержит пути кода, которые могут привести к System.IDisposable.Dispose нескольким вызовам или эквиваленту Dispose, например метод Close() для некоторых типов в одном объекте.

Примечание.

Это правило устарело. Дополнительные сведения см. в разделе "Устаревшие правила".

Описание правила

Правильно реализованный Dispose метод можно вызывать несколько раз, не вызывая исключения. Однако это не гарантируется и не следует вызывать System.ObjectDisposedExceptionDispose несколько раз в объекте.

Устранение нарушений

Чтобы устранить нарушение этого правила, измените реализацию таким образом, чтобы независимо от пути Dispose кода вызывается только один раз для объекта.

Когда лучше отключить предупреждения

Для этого правила отключать вывод предупреждений не следует. Даже если Dispose объект, как известно, является безопасным вызовом несколько раз, реализация может измениться в будущем.

Пример 1

Вложенные using операторы (Using в Visual Basic) могут привести к нарушениям предупреждения CA2202. Если ресурс IDisposable вложенной внутренней using инструкции содержит ресурс внешней using инструкции, Dispose метод вложенного ресурса освобождает содержащийся ресурс. При возникновении этой ситуации метод внешней using инструкции пытается Dispose удалить свой ресурс во второй раз.

В следующем примере объект, созданный во внешнем операторе using, Stream освобождается в конце внутренней инструкции using в методе StreamWriter Dispose объекта, содержащего stream объект. В конце внешней using инструкции stream объект освобождается во второй раз. Второй выпуск является нарушением CA2202.

using (Stream stream = new FileStream("file.txt", FileMode.OpenOrCreate))
{
    using (StreamWriter writer = new StreamWriter(stream))
    {
        // Use the writer object...
    }
}

Пример 2

Чтобы устранить эту проблему, используйте try/finally блок вместо внешней using инструкции. В блоке finally убедитесь, что stream ресурс не имеет значения NULL.

Stream stream = null;
try
{
    stream = new FileStream("file.txt", FileMode.OpenOrCreate);
    using (StreamWriter writer = new StreamWriter(stream))
    {
        stream = null;
        // Use the writer object...
    }
}
finally
{
    stream?.Dispose();
}

Совет

Приведенный ?. выше синтаксис является оператором null-условным.

См. также