Compartilhar via


CA2000: Descartar objetos antes de perder escopo

TypeName

DisposeObjectsBeforeLosingScope

CheckId

CA2000

Category (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 elimina um aviso desta regra a menos que você chame um método no 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 é 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 emiçã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 emiçã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

Implementing Finalize and Dispose