CA1063: следует правильно реализовывать IDisposable
TypeName |
ImplementIDisposableCorrectly |
CheckId |
CA1063 |
Категория |
Microsoft.Design |
Критическое изменение |
Не критическое |
Причина
IDisposable реализован неправильно. Далее перечислены некоторые возможные причины данной проблемы.
IDisposable повторно реализован в классе.
Метод "Finalize" переопределен.
Метод "Dispose" переопределен.
"Dispose()" не является открытым, запечатанным или не имеет имя "Dispose".
"Dispose(bool)" является незащищенным, виртуальным или незапечатанным.
В незапечатанных типах "Dispose()" должен вызывать "Dispose(true)".
В незапечатанных типах реализация метода "Finalize" не вызывает ни метод "Dispose(bool)", ни метод завершения класса.
Нарушение любого из этих шаблонов приведет к выводу предупреждения.
Каждый незапечатанный корневой тип IDisposable должен предоставлять собственный виртуальный метод Dispose(bool) с типом void. Метод "Dispose()" должен вызывать "Dipose(true)", а метод "Finalize" — "Dispose(false)". При создании незапечатанного корневого типа IDisposable необходимо определить метод "Dispose(bool)" и вызывать его. Дополнительные сведения см. в подразделе Очистка неуправляемых ресурсов раздела Руководство по разработке библиотек классов документации по .NET Framework.
Описание правила
Все типы IDisposable должны правильно реализовывать шаблон "Dispose".
Устранение нарушений
Проверьте код и выберите решение, подходящее для устранения нарушения.
Удалите IDisposable из списка интерфейсов, реализованных с помощью {0} и переопределите базовый класс реализации "Dispose".
Удалите метод завершения из типа {0}, переопределите метод "Dispose(bool disposing)" и поместите логику завершения в путь к коду, где "disposing" имеет значение "false".
Удалите {0}, переопределите метод "Dispose(bool disposing)" и поместите логику dispose в путь к коду, где "disposing" имеет значение "false".
Убедитесь, что {0} объявлен как открытый и запечатанный.
Переименуйте {0} на "Dispose" и убедитесь, что он объявлен как открытый и запечатанный.
Убедитесь, что {0} объявлен как защищенный, виртуальный и распечатанный.
Измените {0} так, чтобы он вызывал метод "Dispose(true)", затем метод "GC.SuppressFinalize" в экземпляре текущего объекта ("this" или "Me" в Visual Basic), а затем возвращал результат.
Измените {0} так, чтобы он вызывал метод "Dispose(false)", а затем возвращался.
При написании незапечатанного корневого класса IDisposable убедитесь, что реализация IDisposable выполняется в соответствии с описанным выше шаблоном.
Отключение предупреждений
Для этого правила отключать вывод предупреждений не следует.
Пример псевдокода
В следующем псевдокоде представлен общий пример реализации метода "Dispose(bool)" в классе, использующем управляемые и собственные ресурсы.
public class Resource : IDisposable
{
private IntPtr nativeResource = Marshal.AllocHGlobal(100);
private AnotherResource managedResource = new AnotherResource();
// Dispose() calls Dispose(true)
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// NOTE: Leave out the finalizer altogether if this class doesn't
// own unmanaged resources itself, but leave the other methods
// exactly as they are.
~Resource()
{
// Finalizer calls Dispose(false)
Dispose(false);
}
// The bulk of the clean-up code is implemented in Dispose(bool)
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// free managed resources
if (managedResource != null)
{
managedResource.Dispose();
managedResource = null;
}
}
// free native resources if there are any.
if (nativeResource != IntPtr.Zero)
{
Marshal.FreeHGlobal(nativeResource);
nativeResource = IntPtr.Zero;
}
}
}