Aug 22 2012
Like a lot of engineers I participate in my company’s hiring process by conducting technical interviews with candidates. And like a lot of engineers I have a stable of questions that I draw on repeatedly. I try to vary them somewhat, and add and subtract from the list as technology changes, but a few of them have persisted for years. One of these, on the topic of C#, is: why would the author of a class need to implement IDisposable? This question has a companion for follow-up: how can you ensure that Dispose is called on a disposable class at runtime? I rarely get to deliver the follow-up, though, because almost nobody gets the first question right.
I didn’t intend for the IDisposable question to end up on my long-term go-to list of interview questions. As I recall I just tossed it out there during an interview one afternoon. The answer I got back was so appalling that I asked the same thing of the next candidate, and the one after that, etc. Next thing you know it’s a tradition. To this day I would say maybe one or two out of every ten candidates has given the correct answer to the question. I’m still perplexed by this. IDisposable is not what you’d call obscure in .Net. It is implemented by many classes in the framework, most commonly in System.IO, System.Net, and of course System.Data, but there are plenty of others too.
I consider IDisposable to be fundamental to the relationship between .NET and the underlying Win32 APIs on which it rests, and so I am often left with a strange conundrum when a candidate doesn’t know what it’s for. Many of these candidates are quite strong in ASP.NET, SQL, and other skills that our company requires. Do I vote them down? Vote them up? Are we passing on a decent developer that would enhance our team because he or she doesn’t recall some bit of .NET trivia? Can you be a good developer, and yet be ignorant enough of the structure of .Net and C# that you can’t explain IDisposable?
The most common incorrect answer that I get, usually accompanied by much hemming and hawing, is that IDisposable is for garbage collection. When would you use it? When you want to garbage collect something, of course. It’s as if I were interviewing an auto mechanic and asked what a differential did and why vehicles need them, and was told that it helped remove heat from the engine. Would you hire that mechanic? I wouldn’t. And yet for some reason I feel bad rejecting someone who is perfectly capable of slapping a web page or a query together, but apparently doesn’t understand much of what’s going on under the hood.
IDisposable does have a vague relationship to .NET garbage collection, in that it patches the holes where garbage collection doesn’t work. Deep in the guts of Windows, well below the .NET layer, live things called handles. A handle is an identifier that is assigned to a system resource when it is created by an API call. You get them back when you create things like device contexts, file descriptors, and streams. When you’re done with them you have to free them. Otherwise they hang around and consume system memory. In short, they leak. In the old days of C we had to carefully write code to clean these up. In the slightly less ancient days of C++ and MFC the destructor mechanism was used for this purpose.
C# has destructors, of a sort, but they do not behave the way that C++ destructors do. In C++ memory management is manual. You control when an object is created, and when it is deleted and the destructor is called. That gives you a nice, deterministic connection between when you no longer need an object and when the resources it owns are freed. In C# you can write a destructor, but it essentially implements the Object.Finalize() method, and it will be called whenever the garbage collector sees fit to reap the object. What this means is that expensive system resources that the object has allocated, handles in other words, hang around for an unpredictable amount of time.
Enter IDisposable and the ‘using’ clause. If an object implements IDisposable then it supports a method called Dispose(). Dispose() is meant to be called when you are through with an object, but before the object is garbage collected. Inside Dispose() you can get rid of all those pesky .NET wrappers around pesky COM wrappers around memory-hogging system handles. If you instantiate your object with the ‘using’ clause, then when control passes beyond the end of the ‘using’ block Dispose() will be called on the object automatically. It’s the closest thing to C++ destructor semantics that C# has to offer.
So now, if you ever interview with our company, there should be no reason why you can’t tell me what IDisposable is for.