How to satisfy CA2202 (Do not dispose objects mult

2019-01-26 20:45发布

问题:

This question may seem to you duplicate of CA2202, how to solve this case which has an accepted answer. But you may realize that accepted answer has 5 down votes based on poor quality. Also any other up voted answers are not actually solves the issue. Most of them explains how to suppress the rule or debates about how wrong this rule is and why we should ignore it. Since that rule is there, there should be a way to satisfy it and I'm looking for community support to solve that issue.

I'm trying to figure it out how to satisfy CA2202 in the following code. I understand that the issue here is, using statement also disposes the encryptedStream object. But if I remove the finally part, it starts to throw CA2000

So, what is the correct way of writing it to comply with CA2202 and CA2000

byte[] result;

MemoryStream encryptedStream = null;
try
{
    encryptedStream = new MemoryStream();
    using (var cryptStream = new CryptoStream(encryptedStream, cryptoTransform, CryptoStreamMode.Write))
    {
        cryptStream.Write(inputInBytes, 0, inputInBytes.Length);
        cryptStream.FlushFinalBlock();
        result = encryptedStream.ToArray();
    }
}
finally
{
    encryptedStream?.Dispose();
}
string output = Convert.ToBase64String(result);

回答1:

This is a literal answer to your question, in that it will not issue CA warnings without suppressing them, and will only ever call every Dispose once:

MemoryStream encryptedStream = null;
CryptoStream cryptStream = null;
try {
    encryptedStream = new MemoryStream();
    cryptStream = new CryptoStream(encryptedStream, cryptoTransform, CryptoStreamMode.Write);
    cryptStream.Write(inputInBytes, 0, inputInBytes.Length);
    cryptStream.FlushFinalBlock();
    result = encryptedStream.ToArray();
} finally {
    if (cryptStream != null) {
        cryptStream.Dispose();
   } else {
        if (encryptedStream != null) encryptedStream.Dispose();
   }
}
string output = Convert.ToBase64String(result);

But any developer worth their salt should take a look at this and go "hmm, it's like they didn't know using, I'd better rewrite that". Do not do this in production code. Suppress the warning. Getting code like this correct (and having it remain correct in the face of changes) is actually harder than writing code that uses using with suppression of spurious warnings (indeed, I'm not entirely sure the above code is correct!). It defeats the entire point of having static code analysis in the first place: to write reliable code. You should see code analysis as a tool, not an arbiter of correctness.



回答2:

Really, really, suppress the warning. The warning is wrong. It's okay to do. :-)

Do a Google search for "CA2202 nested using" and you will find dozens of stackoverflow and MSDN forum posts on this issue. https://www.google.com/search?q=ca2202+nested+using

Ultimately, CA2202 and CA2000 are limited because they can't understand the behavior of nested IDisposable objects. Some streams can be configured to leave the underlying stream open, but usually they don't. Suppression really is the correct solution. The problem is that you are trying to be a good citizen, so you are trying to comply with the warnings you are given. But static analysis just isn't smart enough to handle this.