The following code is a simplified extract from part of our production code. It calculates the SHA256 hash for a file and returns it as a string, or returns null
if the file cannot be accessed:
private static string CalculateHash(string fileName)
{
try
{
string result;
using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider())
{
byte[] data = File.ReadAllBytes(fileName);
result = BitConverter.ToString(sha256.ComputeHash(data));
}
Debug.WriteLine("Calculated hash for '" + fileName + "': " + result, 3);
return result;
}
catch (UnauthorizedAccessException ex)
{
Debug.WriteLine("The hash calculation failed: " + ex.Message, 3);
return null;
}
catch (IOException ex)
{
Debug.WriteLine("The hash calculation failed: " + ex.Message, 3);
return null;
}
}
One of our developers recently refactored the code using an exception filter to reduce the duplicate catch
blocks, so it now looks like this:
private static string CalculateHash(string fileName)
{
try
{
string result;
using (SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider())
{
byte[] data = File.ReadAllBytes(fileName);
result = BitConverter.ToString(sha256.ComputeHash(data));
}
Debug.WriteLine("Calculated hash for '" + fileName + "': " + result, 3);
return result;
}
catch (Exception ex) when (ex is UnauthorizedAccessException || ex is IOException)
{
Debug.WriteLine("The hash calculation failed: " + ex.Message, 3);
return null;
}
}
However we now get a code analysis warning:
CA2000 - In method 'CalculateHash(string)', call System.IDisposable.Dispose on object 'sha256' before all references to it are out of scope.
As far as I can see, the SHA256CryptoServiceProvider
is being disposed correctly here, and that will happen whether the exception is caught by the filter or not.
Is this CA2000 a false positive, or has the exception filter created a scenario where the disposal won't happen?