CA1816: Chamar GC.SuppressFinalize corretamente
Property | Valor |
---|---|
ID da regra | CA1816 |
Título | Chamar GC.SuppressFinalize corretamente |
Categoria | Usage |
Correção interruptiva ou sem interrupção | Sem interrupção |
Habilitado por padrão no .NET 8 | Como sugestão |
Causa
As violações dessa regra podem ser causadas por:
Em uma classe não selada, um método que é uma implementação de IDisposable.Dispose e não chama GC.SuppressFinalize.
Um método que não é uma implementação de IDisposable.Dispose e chamadas GC.SuppressFinalize.
Um método que chama GC.SuppressFinalize e passa algo diferente disso (C#) ou Me (Visual Basic).
Descrição da regra
O método IDisposable.Dispose permite que os usuários liberem recursos a qualquer momento antes que o objeto fique disponível para coleta de lixo. Se o método IDisposable.Dispose for chamado, ele liberará recursos do objeto. Isso torna a finalização desnecessária. IDisposable.Dispose deve chamar GC.SuppressFinalize para que o coletor de lixo não chame o finalizador do objeto.
Para evitar que tipos derivados com finalizadores precisem reimplementar IDisposable e chamá-los, tipos não selados sem finalizadores ainda devem chamar GC.SuppressFinalize.
Como corrigir violações
Para corrigir uma violação desta regra:
Se o método for uma implementação de Dispose, adicione uma chamada a GC.SuppressFinalize.
Se o método não for uma implementação de Dispose, remova a chamada para GC.SuppressFinalize ou mova-a para a implementação do tipo Dispose.
Altere todas as chamadas para GC.SuppressFinalize para passar isso (C#) ou Me (Visual Basic).
Se o tipo não for feito para ser substituído, marque-o como
sealed
.
Quando suprimir avisos
Suprime apenas um aviso dessa regra se você estiver usando GC.SuppressFinalize deliberadamente para controlar o tempo de vida de outros objetos. Não suprime um aviso dessa regra se uma implementação de Dispose não chamar GC.SuppressFinalize. Nessa situação, não suprimir a finalização degrada o desempenho e não oferece benefícios.
Suprimir um aviso
Para suprimir apenas uma violação, adicione diretivas de pré-processador ao arquivo de origem a fim de desabilitar e, em seguida, reabilitar a regra.
#pragma warning disable CA1816
// The code that's violating the rule is on this line.
#pragma warning restore CA1816
Para desabilitar a regra em um arquivo, uma pasta ou um projeto, defina a severidade como none
no arquivo de configuração.
[*.{cs,vb}]
dotnet_diagnostic.CA1816.severity = none
Para obter mais informações, confira Como suprimir avisos de análise de código.
Exemplo que viola CA1816
Esse código mostra um método que chama GC.SuppressFinalize, mas não passa isso (C#) ou Me (Visual Basic). Como resultado, esse código viola a regra CA1816.
Public Class DatabaseConnector
Implements IDisposable
Private _Connection As New SqlConnection
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
' Violates rules
GC.SuppressFinalize(True)
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
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;
}
}
}
}
Exemplo que satisfaz CA1816
Este exemplo mostra um método que chama GC.SuppressFinalize corretamente passando isso (C#) ou Me (Visual Basic).
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
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;
}
}
}
}
Regras relacionadas
- CA2215: Métodos Dispose devem chamar o descarte da classe base
- CA2216: Tipos descartáveis devem declarar o finalizador