CA1063: Implementar IDisposable corretamente
Propriedade | valor |
---|---|
ID da regra | CA1063 |
Cargo | Implementar IDisposable corretamente |
Categoria | Desenho |
A correção está quebrando ou não quebrando | Sem quebra |
Habilitado por padrão no .NET 8 | Não |
Causa
A System.IDisposable interface não está implementada corretamente. Possíveis razões para isso incluem:
- IDisposable é reimplementado na classe.
Finalize
é novamente anulada.Dispose()
é anulada.- O
Dispose()
método não é público, selado ou chamado Dispose. Dispose(bool)
não está protegido, virtual ou sem lacre.- Em tipos não lacrados,
Dispose()
deve chamarDispose(true)
. - Para tipos sem lacre, a
Finalize
implementação não chama um ou ambosDispose(bool)
ou o finalizador de classe base.
A violação de qualquer um desses padrões aciona o aviso CA1063.
Cada tipo sem lacre que declara e implementa a IDisposable interface deve fornecer seu próprio protected virtual void Dispose(bool)
método. Dispose()
deve chamar , e o finalizador deve chamar Dispose(true)
Dispose(false)
. Se você criar um tipo sem lacre que declara e implementa a IDisposable interface, você deve defini-lo Dispose(bool)
e chamá-lo. Para obter mais informações, consulte Limpar recursos não gerenciados (guia .NET) e Implementar um método Dispose.
Por padrão, essa regra examina apenas tipos visíveis externamente, mas isso é configurável.
Descrição da regra
Todos os IDisposable tipos devem implementar o padrão Dispose corretamente.
Como corrigir violações
Examine seu código e determine qual das seguintes resoluções corrigirá essa violação:
Remova IDisposable da lista de interfaces que são implementadas pelo seu tipo e substitua a classe base Dispose implementation em vez disso.
Remova o finalizador do seu tipo, substitua Dispose(bool disposing) e coloque a lógica de finalização no caminho do código onde 'disposing' é false.
Substitua Dispose(bool disposing) e coloque a lógica dispose no caminho do código onde 'disposing' é true.
Certifique-se de que Dispose() é declarado como público e selado.
Renomeie seu método de descarte para Eliminar e certifique-se de que ele seja declarado como público e lacrado.
Certifique-se de que Dispose(bool) está declarado como protegido, virtual e sem lacre.
Modifique Dispose() para que ele chame Dispose(true), em seguida, chame SuppressFinalize a instância do objeto atual (
this
, ouMe
no Visual Basic) e, em seguida, retorne.Modifique seu finalizador para que ele chame Dispose(false) e, em seguida, retorne.
Se você criar um tipo sem lacre que declare e implemente a interface, certifique-se de que a IDisposable implementação do IDisposable segue o padrão descrito anteriormente nesta seção.
Quando suprimir avisos
Não suprima um aviso desta regra.
Nota
Poderá ver avisos falsos positivos desta regra se se aplicarem todas as seguintes condições:
- Você está usando o Visual Studio 2022 versão 17.5 ou posterior com uma versão mais antiga do SDK do .NET, ou seja, .NET 6 ou anterior.
- Você está usando os analisadores do SDK do .NET 6 ou uma versão mais antiga dos pacotes do analisador, como Microsoft.CodeAnalysis.FxCopAnalyzers.
- Você tem atributos em sua
IDispose
implementação.
Neste caso, é seguro suprimir um aviso falso positivo. Os falsos positivos são devidos a uma mudança de quebra no compilador C#. Considere o uso de um analisador mais recente que contenha a correção para os avisos de falsos positivos. Atualize para Microsoft.CodeAnalysis.NetAnalyzers versão 7.0.0-preview1.22464.1 ou mais recente ou use os analisadores do SDK do .NET 7.
Configurar código para análise
Use a opção a seguir para configurar em quais partes da sua base de código executar essa regra.
Você pode configurar essa opção apenas para esta regra, para todas as regras às quais ela se aplica ou para todas as regras nesta categoria (Design) às quais ela se aplica. Para obter mais informações, consulte Opções de configuração da regra de qualidade de código.
Incluir superfícies de API específicas
Você pode configurar em quais partes da sua base de código executar essa regra, com base em sua acessibilidade. Por exemplo, para especificar que a regra deve ser executada somente na superfície de API não pública, adicione o seguinte par chave-valor a um arquivo .editorconfig em seu projeto:
dotnet_code_quality.CAXXXX.api_surface = private, internal
Exemplo de pseudocódigo
O pseudocódigo a seguir fornece um exemplo geral de como Dispose(bool)
deve ser implementado em uma classe que usa recursos gerenciados e nativos.
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);
}
}