views:

69

answers:

2

I have a class that implements IDisposable

public class Foo: IDisposable {
    public void Dispose() {
        // do the disposing
    }
}

Then I have a method that uses the class in the following manner:

void Bar() {
    using (var f = new Foo()) {
       // do whatever
    }  
}

When the code leaves the using {...} boundary, the Dispose method on the Foo class gets called. How can I detect in the Dispose method whether the code is leaving using block voluntarily or as a result of an exception?

+1  A: 

You cannot, to the best of my knowledge. Consider changing Foo to a method that takes the "body" to wrap and execute as a lambda:

Foo(f => {
    // do whatever
});

Then, your implementation of Foo can wrap the call into try/catch to detect exceptions and do whatever you want to do (and then rethrow using throw;).

Pavel Minaev
That's a great idea, thx.
AngryHacker
A: 

You shouldn't do that -- and I can't imagine a way to do that.

The main idea of implementing IDisposable is to ensure that resources are freed when destroying the object.

Now, the main idea of the using construct is to ensure that after it, all the resources used by the object are freed.

So, you should not depend on why the object is being disposed to perform this operation. If you do so, you should review your design.

Bruno Reis
There's a school of thought that views `IDisposable` and `using` as general-purpose RAII mechanisms, usable for more than freeing resources. In that scenario, it is perfectly normal to distinguish between "on success" and "on failure" scenarios - e.g. in D there's first-class language support for that, with `scope(success)` and `scope(failure)`; in C++, one would use `std::uncaught_exception()`; etc.
Pavel Minaev
@Bruno. Yes, what Pavel said. The using keyword is absolutely awesome for scoping and using it in combination with Dispose is very powerful.
AngryHacker