Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
| Свойство | Значение |
|---|---|
| Идентификатор правила | CA1063 |
| Заголовок | Правильно реализуйте IDisposable |
| Категория | Проектирование |
| Исправление является критическим или не критическим | неразрывный |
| Включен по умолчанию в .NET 10 | Нет |
| Применимые языки | C# и Visual Basic |
Причина
Интерфейс System.IDisposable реализован неправильно. Возможные причины:
- IDisposable реализован в классе;
-
Finalizeпереопределяется снова; -
Dispose()переопределяется; - метод
Dispose()не является открытым, запечатанным или именованным методом Dispose; -
Dispose(bool)не является защищенным, виртуальным или незапечатанным; - в незапечатанных типах
Dispose()должен вызыватьDispose(true); - Для незапечатанных типов реализация
Finalizeне вызывает ни один из методовDispose(bool)или финализатор базового класса.
Нарушение любого из этих шаблонов вызывает предупреждение CA1063.
Каждый незапечатанный тип, объявляющий и реализующий интерфейс IDisposable, должен предоставить собственный метод protected virtual void Dispose(bool).
Dispose() должен вызывать Dispose(true), а финализатор должен вызывать Dispose(false). При создании незапечатанного типа, объявляющего и реализующего интерфейс IDisposable, необходимо определить Dispose(bool) и вызвать его. Дополнительные сведения см. в разделе "Очистка неуправляемых ресурсов" (руководство по .NET) и реализация метода Dispose.
По умолчанию это правило проверяет только видимые извне типы, но это поведение можно настроить.
Описание правила
Все типы IDisposable должны правильно реализовывать шаблон Dispose.
Устранение нарушений
Проверьте свой код и определите, какое из следующих разрешений исправит это нарушение.
Удалите IDisposable из списка интерфейсов, реализуемых вашим типом, и переопределите метод Dispose базового класса.
Удалите финализатор из типа, переопределите Dispose(bool disposing) и перенесите логику окончания в код, где "disposing" имеет значение false.
Переопределите метод Dispose(bool disposing) и разместите логику очистки в блоке кода, где "disposing" равно true.
Убедиться, что метод Dispose() объявлен как открытый и запечатанный.
Переименовать метод dispose в Dispose и убедиться, что он объявлен как открытый и запечатанный.
Убедитесь, что Dispose(bool) объявлен как защищённый, виртуальный и нескрытый.
Изменить Dispose() так, чтобы он вызывал Dispose(true), а затем вызывал SuppressFinalize в текущем экземпляре объекта (
thisилиMeв Visual Basic), а затем выполнял возврат.Изменить метод завершения так, чтобы он вызывал Dispose(false), а затем выполнял возврат.
Если вы создаёте незапечатанный тип, объявляющий и реализующий интерфейс IDisposable, убедитесь, что реализация IDisposable соответствует шаблону, описанному ранее в этом разделе.
Когда лучше отключить предупреждения
Для этого правила отключать вывод предупреждений не следует.
Примечание.
В этом правиле могут отображаться предупреждения о ложноположительных срабатываниях, если применяются все указанные ниже действия.
- Вы используете Visual Studio 2022 версии 17.5 или более поздней версии с более старой версией пакета SDK для .NET, то есть .NET 6 или более ранней версии.
- Вы используете анализаторы из пакета SDK для .NET 6 или более старой версии пакетов анализатора, например Microsoft.CodeAnalysis.FxCopAnalyzers.
- В реализации есть атрибуты
IDispose.
В этом случае это безопасно для подавления ложноположительных предупреждений. Ложные срабатывания обусловлены критическим изменением компилятора C#. Рассмотрите возможность использования более нового анализатора, содержащего исправление для предупреждений о ложных срабатываниях. Обновление до Microsoft.CodeAnalysis.NetAnalyzers версии 7.0.0-preview1.22464.1 или более поздней версии или использование анализаторов из пакета SDK для .NET 7.
Настройка кода для анализа
Используйте следующий параметр, чтобы выбрать части базы кода для применения этого правила.
Этот параметр можно настроить только для этого правила, для всех правил, к которым он применяется, или для всех правил в этой категории (конструкторе), к которым она применяется. Дополнительные сведения см. в статье Параметры конфигурации правила качества кода.
Включите конкретные поверхности API
Вы можете настроить компоненты базы кода для выполнения этого правила на основе их специальных возможностей, задав параметр api_surface. Например, чтобы указать, что правило должно выполняться только для непубличной поверхности API, добавьте следующую пару "ключ-значение" в файл .editorconfig в ваш проект:
dotnet_code_quality.CAXXXX.api_surface = private, internal
Примечание.
Замените XXXX частью CAXXXX идентификатором применимого правила.
Пример псевдокода
Следующий псевдокод предоставляет общий пример того, как Dispose(bool) следует реализовать в классе, использующем управляемые и нативные ресурсы.
public class Resource : IDisposable
{
private bool isDisposed;
private IntPtr nativeResource = Marshal.AllocHGlobal(100);
private AnotherResource managedResource = new AnotherResource();
// Dispose() calls Dispose(true)
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// The bulk of the clean-up code is implemented in Dispose(bool)
protected virtual void Dispose(bool disposing)
{
if (isDisposed) return;
if (disposing)
{
// free managed resources
managedResource.Dispose();
}
// free native resources if there are any.
if (nativeResource != IntPtr.Zero)
{
Marshal.FreeHGlobal(nativeResource);
nativeResource = IntPtr.Zero;
}
isDisposed = true;
}
// NOTE: Leave out the finalizer altogether if this class doesn't
// own unmanaged resources, but leave the other methods
// exactly as they are.
~Resource()
{
// Finalizer calls Dispose(false)
Dispose(false);
}
}