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

IDisposable

Implementando finalizar e Dispose para limpeza de recursos não gerenciados