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


CA1816: вызов GC.SuppressFinalize должен осуществляться правильно

TypeName

CallGCSuppressFinalizeCorrectly

CheckId

CA1816

Категория

Microsoft. Использование

Критическое изменение

Не критическое

Причина

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

Метод IDisposable.Dispose позволяет пользователям освобождать ресурсы в любое время, прежде чем объект становится доступным для сборки мусора. Если вызвать метод IDisposable.Dispose, ресурсы объекта будут очищены. Это делает финализацию ненужной. IDisposable.Dispose должен вызвать GC.SuppressFinalize, чтобы сборщик мусора не вызывал метод завершения объекта.

 

Чтобы исключить необходимость повторной реализации [System.IDisposable] производными типами с методами завершения, а также для его вызова, незапечатанные типы без методов завершения должны по-прежнему вызывать GC.SuppressFinalize.

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

Чтобы устранить нарушение этого правила, выполните следующие действия

Если метод является реализацией Dispose, добавьте вызов GC.SuppressFinalize.

Если метод не является реализацией Dispose, удалите вызов GC.SuppressFinalize или переместите его в реализацию типа Dispose.

Измените все вызовы GC.SuppressFinalize для передачи этого (Me в Visual Basic).

Отключение предупреждений

Отключать вывод предупреждения по этому правилу следует только в том случае, если рассматривается возможность использования GC.SuppressFinalize для управления временем жизни других объектов. Не отключайте вывод предупреждений по этому правилу, если реализация Dispose не вызывает GC.SuppressFinalize. В этом случае, невозможность отключения завершения отрицательно сказывается на производительности и не дает положительных результатов.

Пример

В следующем примере показан метод, неправильно вызывающий GC.SuppressFinalize.

Imports System
Imports System.Data.SqlClient

Namespace Samples

    Public Class DatabaseConnector
        Implements IDisposable

        Private _Connection As New SqlConnection

        Public Sub Dispose() Implements IDisposable.Dispose
            Dispose(True)
            GC.SuppressFinalize(True)   ' Violates rules
        End Sub

        Protected Overridable Sub Dispose(ByVal disposing As Boolean)
            If disposing Then
                If _Connection IsNot Nothing Then
                    _Connection.Dispose()
                    _Connection = Nothing
                End If
            End If
        End Sub

    End Class

End Namespace
using System;
using System.Data.SqlClient;
namespace Samples
{
    public class DatabaseConnector : IDisposable
    {
        private SqlConnection _Connection = new SqlConnection();

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(true);  // Violates rule
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_Connection != null)
                {
                    _Connection.Dispose();
                    _Connection = null;
                }
            }
        }
    }
}

В следующем примере показан метод, правильно вызывающий GC.SuppressFinalize.

Imports System
Imports System.Data.SqlClient

Namespace Samples

    Public Class DatabaseConnector
        Implements IDisposable

        Private _Connection As New SqlConnection

        Public Sub Dispose() Implements IDisposable.Dispose
            Dispose(True)
            GC.SuppressFinalize(Me)
        End Sub

        Protected Overridable Sub Dispose(ByVal disposing As Boolean)
            If disposing Then
                If _Connection IsNot Nothing Then
                    _Connection.Dispose()
                    _Connection = Nothing
                End If
            End If
        End Sub

    End Class

End Namespace
using System;
using System.Data.SqlClient;

namespace Samples
{
    public class DatabaseConnector : IDisposable
    {
        private SqlConnection _Connection = new SqlConnection();

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_Connection != null)
                {
                    _Connection.Dispose();
                    _Connection = null;
                }
            }
        }
    }
}

Связанные правила

CA2215: методы Dispose должны вызывать такие же методы базового класса

CA2216: высвобождаемые типы должны объявлять метод завершения

См. также

Ссылки

Реализация методов Finalize и Dispose для очистки неуправляемых ресурсов