7

Objects that derive from HashAlgorithm such as MD5CryptoServiceProvider have a Dispose() method, but it's private. Instead it has a Clear() method which "Releases all resources" used by it.

WTF?

Is this how to correctly dispose of a HashAlgorithm then?

var hasher = new MD5CryptoServiceProvider();

byte[] hashCode = hasher.ComputeHash(data);

hasher.Clear();

Someone wanna explain this one to me? :)

core
  • 32,451
  • 45
  • 138
  • 193
  • I recommend you to use another hashing algorithm too if you can as many deem the MD5 hash unsafe in certain applications. A good alternative would be the SHA-family, like SHA 256. They are available for use in .NET too. – Skurmedel Apr 17 '09 at 18:49
  • 1
    Good call. I remember reading MD5 had been proved vulnerable a few years back. Geeze, this from Wikipedia: "On 18 March 2006, Klima published an algorithm[10] that can find a collision within one minute on a single notebook computer, using a method he calls tunneling." – core Apr 18 '09 at 03:20
  • FYI "why does is implement IDisposable in the first place?" is discussed over here: https://stackoverflow.com/questions/59083838/why-does-the-hashalgorithm-class-implement-idisposable – Brondahl May 19 '22 at 15:13

3 Answers3

13

While the Dipose() method is private, if you cast it to IDisposable you can gain access to it. As others have said, though, Clear() will call it for you.

A better approach, however, is to enclose the declaration and and assignment of the variable in a using() block:

byte[] hashCode;

using(var hasher = new MD5CryptoServiceProvider())
{
    hashCode = hasher.ComputeHash(data);
}
Adam Robinson
  • 182,639
  • 35
  • 285
  • 343
5

Looking with Reflector, the Clear method of HashAlgorithm simply calls the private Dispose method. The reason for exposing a method with name Clear was probably just that the designers of the class thought it would be a more suitable name for a hash algorithm. You see similar styles within other parts of the BCL, such as Close for System.IO.Stream. Also, best practice here is to use a using block, which will automatically call the private Dispose method when it's finished.

Noldorin
  • 144,213
  • 56
  • 264
  • 302
  • 1
    As mentioned by others, it's best to use a `using` block anyway, which simplifies the try-finally/dispose logic for you, and is recommended practice. – Noldorin Apr 17 '09 at 18:41
  • Also, note that reflection also shows that the Dispose method is simply zeroing out an internal array. it's not even releasing the array (not setting to null), its calling Array.Clear. It doesn't seem to do any unmanaged releasing of any handles or other. i think that if one 'forgot' to dispose this class, there'd be no leak or issue other than a security issue of leaving a previous hash value behind in memory. – iQueue Apr 28 '18 at 16:43
-5

You should let the GC handle that for you. That's it's job.

Some resources should be disposed of, like DB connections and file handles, so put those in a using block (C#). This isn't one of those cases, though.

Alex Fort
  • 18,459
  • 5
  • 42
  • 51
  • Actually, HashAlgorithm (and thus MD5CryptoServiceProvider) *do* implement IDisposable, therefore they should be properly disposed, either by calling the Clear method or with a `using` block. – Noldorin Apr 17 '09 at 18:40
  • 4
    Just because the class implements IDisposable, doesn't mean it needs to be disposed of manually. To each his own, though. – Alex Fort Apr 17 '09 at 18:41
  • No indeed, but the fact that it *does* implement IDisposable almost always strongly signifies that it ought to be manually disposed because it's doing some native interop inside. The GC will eventually get around to disposing it even if you don't explicitly call the method, but the time at which this occurs is not guaranteed to be soon – Noldorin Apr 17 '09 at 18:43
  • 4
    @Alex: Actually that's 100% incorrect. If it implements IDisposable, you are ALWAYS supposed to explicitly call Dispose(). While good design would say that the Finalizer on the class should call Dispose() if an error in your code failed to, there is nothing technically requiring that. If it implements IDisposable, call Dispose(). – Adam Robinson Apr 17 '09 at 18:44
  • HashAlgorithm does implement IDisposable – Simon Mar 31 '10 at 05:55
  • 1
    @AdamRobinson do you dispose all `Tasks in your code? – Shadow Oct 29 '21 at 12:40
  • FYI, whether it's needed and what it's doing is discussed over here: https://stackoverflow.com/questions/59083838/why-does-the-hashalgorithm-class-implement-idisposable – Brondahl May 19 '22 at 15:12