CA2000: Descartar objetos antes de perder escopo
TypeName |
DisposeObjectsBeforeLosingScope |
CheckId |
CA2000 |
<strong>Categoria</strong> |
Microsoft.Reliability |
Alteração significativa |
Não-separável |
Causa
Um objeto local de um IDisposable tipo é criado, mas o objeto não for descartado antes de todas as referências ao objeto estão fora do escopo.
Descrição da regra
Se um objeto descartável não é descartado explicitamente antes de todas as referências a ele estão fora do escopo, o objeto será descartado em algum momento indeterminado quando o coletor de lixo executa o finalizador do objeto. Porque um evento excepcional pode ocorrer que impedirá o finalizador do objeto seja executado, o objeto deve ser explicitamente destruído em vez disso.
Como corrigir violações
Para corrigir uma violação desta regra, chamada Dispose sobre o objeto antes de todas as referências a ele estão fora do escopo.
Observe que você pode usar o using instrução (Using na Visual Basic) para encapsular os objetos que implementam IDisposable. Os objetos que são dispostos dessa maneira serão descartados automaticamente no fechamento do using bloco.
A seguir estão algumas situações onde a instrução using não é suficiente para proteger os objetos de IDisposable e pode causar CA2000 ocorra.
Retornar um objeto descartável requer que o objeto é construído em um bloco try/finally fora de uso de um bloco.
Inicializar membros de um objeto descartável não deve ser feito no construtor do uso de uma instrução.
Aninhando construtores são protegidos somente pelo manipulador de exceção. Por exemplo,
using (StreamReader sr = new StreamReader(new FileStream("C:\myfile.txt", FileMode.Create))) { ... }
faz com que CA2000 ocorrer devido uma falha na construção do objeto StreamReader pode resultar em um objeto FileStream nunca sendo fechado.
Objetos dinâmicos devem usar um objeto de sombra para implementar o padrão Dispose de objetos de IDisposable.
Quando suprimir avisos
Não suprimir um aviso da regra, a menos que você chamou um método do objeto que chama Dispose, como Close.
Regras relacionadas
CA2213: Campos descartáveis devem ser descartados.
CA2202: Não Dispor objetos várias vezes
Exemplo
Se você estiver implementando um método que retorna um objeto descartável, use um bloco try/finally sem um bloco catch para certificar-se de que o objeto for descartado. Usando um bloco try/finally, você pode permitir exceções para ser gerado no ponto de falha e certifique-se de que o objeto é descartado.
O método OpenPort1, a chamada para abrir o objeto ISerializable SerialPort ou a chamada ao SomeMethod pode falhar. Um aviso de CA2000 é gerado nessa implementação.
No método OpenPort2, dois objetos de SerialPort são nulos declarado e definido como:
tempPort, que é usado para testar as operações do método teve êxito.
port, que é usado para o valor de retorno do método.
O tempPort é construído e aberto em um try bloco e qualquer trabalho necessário é executada na mesma try bloco. No final o try bloco, a porta aberta é atribuído ao port objeto será retornado e a tempPort objeto é definido como null.
O finally bloco verifica o valor da tempPort. Se não for nulo, uma operação no método falhou, e tempPort está fechado para certificar-se de que todos os recursos são liberados. O objeto retornado de porta irá conter o objeto SerialPort aberto se as operações do método teve êxito ou ele será nulo se uma operação falhou.
Public Function OpenPort1(ByVal PortName As String) As SerialPort
Dim port As New SerialPort(PortName)
port.Open() 'CA2000 fires because this might throw
SomeMethod() 'Other method operations can fail
Return port
End Function
Public Function OpenPort2(ByVal PortName As String) As SerialPort
Dim tempPort As SerialPort = Nothing
Dim port As SerialPort = Nothing
Try
tempPort = New SerialPort(PortName)
tempPort.Open()
SomeMethod()
'Add any other methods above this line
port = tempPort
tempPort = Nothing
Finally
If Not tempPort Is Nothing Then
tempPort.Close()
End If
End Try
Return port
End Function
Public Function CreateReader1(ByVal x As Integer) As StreamReader
Dim local As New StreamReader("C:\Temp.txt")
x += 1
Return local
End Function
Public Function CreateReader2(ByVal x As Integer) As StreamReader
Dim local As StreamReader = Nothing
Dim localTemp As StreamReader = Nothing
Try
localTemp = New StreamReader("C:\Temp.txt")
x += 1
local = localTemp
localTemp = Nothing
Finally
If (Not (localTemp Is Nothing)) Then
localTemp.Dispose()
End If
End Try
Return local
End Function
public SerialPort OpenPort1(string portName)
{
SerialPort port = new SerialPort(portName);
port.Open(); //CA2000 fires because this might throw
SomeMethod(); //Other method operations can fail
return port;
}
public SerialPort OpenPort2(string portName)
{
SerialPort tempPort = null;
SerialPort port = null;
try
{
tempPort = new SerialPort(portName);
tempPort.Open();
SomeMethod();
//Add any other methods above this line
port = tempPort;
tempPort = null;
}
finally
{
if (tempPort != null)
{
tempPort.Close();
}
}
return port;
}
Por padrão, o Visual Basic compilador tem todos os operadores aritméticos verificar estouro. Portanto, qualquer operação aritmética de Visual Basic pode lançar uma OverflowException. Isso pode levar a violações de regras como, por exemplo, CA2000 inesperadas. Por exemplo, a função de CreateReader1 a seguir produzirá uma violação de CA2000 porque o compilador Visual Basic está emitindo um estouro de verificação de instrução para a adição que poderia lançar uma exceção que causaria o StreamReader para não ser descartado.
Para corrigir isso, você pode desativar emitindo verificações de estouro pelo compilador de Visual Basic em seu projeto ou pode modificar seu código como no seguinte função de CreateReader2.
Para desativar a emissão de verificações de estouro, o botão direito do mouse no nome do projeto no Solution Explorer e clique em Propriedades. Clique em compilar, clique em Advanced Compile Optionse verifique Remove integer overflow checks.
Consulte também
Referência
Implementando finalizar e Dispose para limpeza de recursos não gerenciados