CA2000: объект не расположен по всем путям исключений

У меня возникли проблемы с попыткой выяснить, почему я получаю это предупреждение в следующем коде.

CA2000 : Microsoft.Reliability : в методе 'Encryption64.Decrypt(String, String)' объект 'des' не размещается по всем путям исключений. Вызовите System.IDisposable.Dispose для объекта 'des' до того, как все ссылки на него будут вне области действия.

CA2000 : Microsoft.Reliability : в методе «Encryption64.Encrypt(String, String)» объект «des» не размещается по всем путям исключений. Вызовите System.IDisposable.Dispose для объекта 'des' до того, как все ссылки на него будут вне области действия.

Public Class Encryption64

    Private key() As Byte = {}
    Private IV() As Byte = {&H12, &H34, &H56, &H78, &H90, &HAB, &HCD, &HEF}

    Public Function Decrypt(ByVal stringToDecrypt As String, ByVal sEncryptionKey As String) As String

        Dim des As New DESCryptoServiceProvider()
        Dim ms As New MemoryStream()
        Dim ReturnValue As String = String.Empty

        Try

            Dim inputByteArray(stringToDecrypt.Length) As Byte
            key = System.Text.Encoding.UTF8.GetBytes(Left(sEncryptionKey, 8))
            inputByteArray = Convert.FromBase64String(stringToDecrypt)

            Dim cs As New CryptoStream(ms, des.CreateDecryptor(key, IV),CryptoStreamMode.Write)
            cs.Write(inputByteArray, 0, inputByteArray.Length)
            cs.FlushFinalBlock()

            Dim encoding As System.Text.Encoding = System.Text.Encoding.UTF8
            ReturnValue = encoding.GetString(ms.ToArray())

        Catch e As Exception

            ReturnValue = e.Message

        Finally

            If des IsNot Nothing Then
                des.Dispose()
            End If

            If ms IsNot Nothing Then
                ms.Dispose()
            End If

        End Try

        Return ReturnValue

    End Function

    Public Function Encrypt(ByVal stringToEncrypt As String, ByVal SEncryptionKey As String) As String

        Dim des As New DESCryptoServiceProvider()
        Dim ms As New MemoryStream()
        Dim ReturnValue As String = String.Empty

        Try

            key = System.Text.Encoding.UTF8.GetBytes(Left(SEncryptionKey, 8))

            Dim inputByteArray() As Byte = Encoding.UTF8.GetBytes(stringToEncrypt)
            Dim cs As New CryptoStream(ms, des.CreateEncryptor(key, IV), CryptoStreamMode.Write)

            cs.Write(inputByteArray, 0, inputByteArray.Length)
            cs.FlushFinalBlock()

            ReturnValue = Convert.ToBase64String(ms.ToArray())

        Catch e As Exception

            ReturnValue = e.Message

        Finally

            If des IsNot Nothing Then
                des.Dispose()
            End If

            If ms IsNot Nothing Then
                ms.Dispose()
            End If

        End Try

        Return ReturnValue

    End Function

End Class

person Hiral Desai    schedule 23.08.2011    source источник


Ответы (2)


Поскольку вы объявляете (и создаете) свои объекты des вне блоков Try... finally, ваш код может вызвать исключение в строке Dim ms As New MemoryStream(), и ваш .Dispose() не будет называется.

Когда вы работаете с объектами, реализующими IDisposable, гораздо предпочтительнее по возможности помещать их в блок Using вместо блока Try...Finally. Например:

Открытая функция Decrypt (ByVal stringToDecrypt As String, ByVal sEncryptionKey As String) As String

    Dim ms As New MemoryStream() 
    Dim ReturnValue As String = String.Empty 

        Dim inputByteArray(stringToDecrypt.Length) As Byte 
        key = System.Text.Encoding.UTF8.GetBytes(Left(sEncryptionKey, 8)) 
        inputByteArray = Convert.FromBase64String(stringToDecrypt) 

        Using ms as New MemoryStream
           Using des As New DESCryptoServiceProvider
              Dim cs As New CryptoStream(ms, des.CreateDecryptor(key, IV),CryptoStreamMode.Write) 
              cs.Write(inputByteArray, 0, inputByteArray.Length) 
              cs.FlushFinalBlock() 
           End Using ' des
           Dim encoding As System.Text.Encoding = System.Text.Encoding.UTF8 
           ReturnValue = encoding.GetString(ms.ToArray()) 
        End Using ' ms 
    Catch e As Exception 

        ReturnValue = e.Message 

    End Try 

    Return ReturnValue 

End Function 
person Jim Wooley    schedule 23.08.2011
comment
Спасибо, работает без проблем! Просто из любопытства, позаботится ли Using об автоматической утилизации для нас? Я довольно много писал код для .Net, но никогда особо не заботился об анализе/оптимизации кода. - person Hiral Desai; 23.08.2011
comment
да. Использование было введено в VB 8 (2003 г.) и обрабатывает вызовы Dispose для обернутых объектов. - person Jim Wooley; 23.08.2011

Просто предположение, но, может быть, он недостаточно умен, чтобы понять, что эта строка кода всегда будет правдой:

If des IsNot Nothing Then

Другими словами, можно предположить, что из-за наличия условного оператора вызов Dispose() может не выполняться.

Чтобы проверить, вы можете попробовать закомментировать «если» и посмотреть, исчезнет ли предупреждение.

person JohnD    schedule 23.08.2011
comment
Не совсем, не получилось. Я также подозревал, что строка Dim cs As New CryptoStream... может генерировать исключение, и в этом случае des не удаляется. Поэтому я попытался поставить еще один Try..Catch..Finally для этих строк, он все еще появлялся с тем же предупреждением. - person Hiral Desai; 23.08.2011