CA2000 and Using Statement

I started with code like this (give-or-take few white-spaces):

using (var aes = new RijndaelManaged() { BlockSize = 128, KeySize = 256, Key = key, IV = iv, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 }) {
this.Transform = aes.CreateEncryptor();
this.Stream = new CryptoStream(stream, this.Transform, CryptoStreamMode.Write);
}

Running code analysis on this returned CA2000 (Microsoft.Reliability) error. It simply stated "In method 'Aes256CbcStream.Aes256CbcStream(Stream, CryptoStreamMode, byte[])', object '<>g__initLocal0' is not disposed along all exception paths. Call System.IDisposable.Dispose on object '<>g__initLocal0' before all references to it are out of scope."

Problem here is that all object references ARE being released by using statement. Or so I thought.

If you are using Object Initializer, compiler will generate code to support it. And that compiler-generated code is culprit for that message. And yes, there is a reason for why it behaves like this.

Personally I often ignore this warning. Strictly speaking this is not a real solution and definitely not a best practice. However it is quite often acceptable. If you are generating just few of these objects and there is no failure expected (famous last words), little bit more work for garbage collector is acceptable scenario.

Real solution for now would be not to use Object Initializer syntax when dealing with using statement. In our example that would mean:

using (var aes = new RijndaelManaged()) {
aes.BlockSize = 128;
aes.KeySize = 256;
aes.Key = key;
aes.IV = iv;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
this.Transform = aes.CreateEncryptor();
this.Stream = new CryptoStream(stream, this.Transform, CryptoStreamMode.Write);
}

Leave a Reply

Your email address will not be published. Required fields are marked *