Why would a class implement IDisposable explicitly instead of implicitly?
Asked Answered
V

4

17

I was using the FtpWebResponse class and didn't see a Dispose method. It turns out that the class implements IDisposable, but does so explicitly so that you must first cast your instance to IDisposable before calling Dispose:

// response is an instance of FtpWebResposne
((IDisposable) response).Dispose();

Why would the designer of a class such as this one choose to implement IDisposable explicitly? As Anthony Pegram says, doing things this way masks the fact that the object should be disposed for the average developer who is not consulting the documentation every time he/she uses a class.

Vanburen answered 25/6, 2010 at 15:30 Comment(0)
M
15

This is normally done if the class has a Close method that is the exact same as Dispose. The original Dispose is hidden in an explicit implementation so that the exact same method doesn't have two names.

It's officially recommended here:

Do implement a Close method for cleanup purposes if such terminology is standard, for example as with a file or socket. When doing so, it is recommended that you make the Close implementation identical to Dispose...

Consider implementing interface members explicitly to hide a member and add an equivalent member with a better name.

Occasionally a domain-specific name is more appropriate than Dispose. For example, a file encapsulation might want to use the method name Close. In this case, implement Dispose privately and create a public Close method that calls Dispose.

(P.S. I disagree with this convention.)

Mitrailleuse answered 25/6, 2010 at 15:44 Comment(5)
I agree, but the weird part here is that the behavior potentially differs. Reflector shows that Dispose() calls Close() and then calls an internal virtual named OnDispose(). Close() doesn't, so you could potentially get different behavior from the 2 methods (although it has no effect on FtpWebResponse because the OnDispose() implementation is empty)Erythropoiesis
What's wrong with two methods having the same name? CLR via C# (p. 546) says that "Some classes that offer the dispose pattern also offer a Close method for convenience; but the dispose pattern doesn't require this method. For example, the System.IO.FileStream class offers the dispose pattern, and this class also offers a Close method. Programmers find it more natural to close a file rather than dispose of a file."Vanburen
@JMarsch: This may be a holdover; .NET 1.1 BCL classes had a number of cases where Close and Dispose did have slightly different behavior. AFAIK, these have all been cleaned up now except for DbConnection and derived types.Mitrailleuse
I agree, it probably is a design holdover, although it appears that the class was introduced in version 2.0. Based on the framework guidelines, it looks as though it follows the guidelines, although it doesn't follow the "recommended that you make the close implementation identical to Dispose.." part.Erythropoiesis
I join you in your disagreement. There is a very strong convention that once one calls Dispose() on an object, no further cleanup will be necessary or possible (it should be possible to e.g. call Dispose again without throwing an exception, but it shouldn't have any effect). There is no such convention surrounding Close. It would be entirely possible for an object to support a Close method, but refrain from cleaning up everything in order to allow for a Reopen method.Bibliomania
A
5
  • Occasionally a class will have a Dispose method that is part of the interface but doesn't actually need to be called because the only resource to dispose of is memory: MemoryStream, for example.
  • As mentioned by others, if the class has a Close method that does the same thing as Dispose, arguably Dispose only needs to exist to support the "using" pattern so it may as well be explicit.
Affable answered 25/6, 2010 at 16:2 Comment(0)
E
1

It's a little weird looking to me too. For what it's worth: the base class (WebResponse) implements a Close() method. Reflector shows that WebResponse's Dispose() method just calls Close() and an Internal OnDispose virtual that does nothing.

I have to confess that it smells a little to me, but I bet that they explicitly implemented IDisposable so that there would not be confusion in Intellisense between calling Close() or Dispose().

Erythropoiesis answered 25/6, 2010 at 15:44 Comment(0)
W
1

In addition to what's been said, I might suggest that implementing IDisposable explicitly encourages use of the using block, as it can be used on any type which implements IDisposable and it is more natural (to most people, anyway) to write this:

using (var response = GetResponse())
{
    // do something
}

Than this:

var response = GetResponse();

// do something

((IDisposable)response).Dispose();

I'm not sure that would be a developer's intention in explicitly implementing IDisposable, but it's possible.

Whirlwind answered 25/6, 2010 at 15:54 Comment(1)
It does encourange use, but only if you know the object is disposable! The problem is that people not consulting the documentation would simply not know. And think of code libraries that might have poor documentation (or none at all).Mclaren

© 2022 - 2024 — McMap. All rights reserved.