Compartilhar via


CA2000: descartar objetos antes de perder o escopo

TypeName

DisposeObjectsBeforeLosingScope

CheckId

CA2000

Categoria

Microsoft.Reliability

Alteração Significativa

Sem quebra

Causa

Um objeto local de um tipo IDisposable é criado mas o objeto não é descartado antes todas as referências para o objeto estarem fora do escopo.

Descrição da Regra

Se um objeto descartável não é descartado explicitamente antes de todas as referências a ele estarem fora do escopo, o objeto será descartado em algum tempo indefinido quando o coletor de lixo executa o finalizador do objeto.Porque um evento excepcional pode ocorrer que impeça o finalizador do objeto de executar, o objeto deve ser explicitamente descartado para evitar isso.

Como Corrigir Violações

Para corrigir uma violação desta regra, chame Dispose no objeto antes todas as referências a ele estarem fora do escopo.

Observe que você pode usar a instrução using (Using em Visual Basic) para envolver os objetos que implementam IDisposable.Os objetos que estão envolvidos assim, serão descartados automaticamente no fechamento do bloco using.

A seguir estão algumas situações onde a instrução using não é suficiente para proteger objetos IDisposable e pode fazer com que CA2000 ocorra.

  • Retornar um objeto descartável requer que o objeto seja construído em um bloco try/finally de fora de um bloco using.

  • A Inicialização de membros de um objeto descartável não deve ser feita no construtor de uma instrução using.

  • Construtores de aninhamento que são protegidos somente por um manipulador de exceção.Por exemplo,

    using (StreamReader sr = new StreamReader(new FileStream("C:\myfile.txt", FileMode.Create)))
    { ... }
    

    faz com que CA2000 ocorra porque uma falha de compilação do objeto StreamReader pode levar ao objeto FileStream nunca ser fechado.

  • Os objetos dinâmicos devem usar um objeto sombra para implementar o padrão da disposição de objetos IDisposable.

Quando Suprimir Alertas

Não suprima um aviso desta regra a menos que você chamar um método no objeto que chama Dispose, como Close, ou se o método que gerou o aviso retorna quebras automáticas de um objeto IDisposable o objeto.

Regras Relacionadas

CA2213: os campos descartáveis devem ser descartados

CA2202: não descartar 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 é descartado.Usando um block try/finally, você permite que exceções sejam levantadas no ponto de falha e certifica-se de que o objeto seja descartado.

No método OpenPort1, a chamada para abrir o objeto SerialPort de ISerializable ou a chamada a SomeMethod podem falhar.Um aviso CA2000 é gerado nesta implementação.

No método OpenPort2, dois objetos de SerialPort são declarados e definidos como null:

  • tempPort, que é usado para testar se operações do método são bem-sucedidas.

  • port, que é usado para valores de retorno do método.

O tempPort é construído e aberto em um bloco try, e qualquer outro trabalho necessário é executada no mesmo bloco try.No final do bloco try, a porta aberta é atribuída ao objeto port que será retornado e o objeto tempPort é definido como null.

O bloco finally verifica o valor de tempPort.Se não for null, uma operação falhou no método, e tempPort é fechado para certificar-se de que todos os recursos sejam liberados.O objeto retornado da porta conterá o objeto aberto SerialPort se as operações de método obtiverem sucesso, ou serão null se uma operação falhar.

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 compilador Visual Basic tem todas as verificação dos operadores aritméticos para overflow.Portanto, qualquer operação aritmética do Visual Basic pode acionar OverflowException.Isso pode levar às violações inesperados nas regras como CA2000.Por exemplo, a função a seguir CreateReader1 gera uma violação CA2000 porque o compilador do Visual Basic está emitindo um overflow que verifica a instrução para a adição que pode lançar uma exceção que faz com que o StreamReader a não seja descartado.

Para corrigir isso, você pode desativar a emissão de verificação de overflow pelo compilador do Visual Basic em seu projeto ou você pode alterar o código como na função CreateReader2.

Para desativar a emissão de verificação de overflow, clique com o botão direito do mouse no nome do projeto no solution Explorer e clique Propriedades.Clique Compilar, clique Opções de Compilação Avançadas, e então marcar Remover verificação de overflow de inteiros.

Consulte também

Referência

IDisposable

Outros recursos

Implementing Finalize and Dispose