Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bad practice? Non-canon usage of c#'s using statement

C# has the using statement, specifically for IDisposable objects. Presumably, any object specified in the using statement will hold some sort of resource that should be freed deterministically.

However, it seems to me that there are many designs in programming which have a single, definite beginning and end, but lack intrinsic language support. The using construct provides an opportunity to use the built in features of a code editor to, at least, clearly and naturally highlight the scope of such a design or operation.

What I have in mind is the sort of operation that frequently starts with a BeginXXX() and EndXXX() method, though there are plenty of different flavors, such as an asynchronous code execution that involves a "start" and a "join".

Take this naive example.

webDataOperation.Start();
GetContentFromHardDrive();
webDataOperation.Join();
// Perform operation that requires data from both sources

What if, instead, the Start method returned an object whose IDisposable.Dispose method performs the join operation.

using(webDataOperation.Start()) {
    GetContentFromHardDrive();
}
// Perform operation that requires data from both sources

Or, better yet, what I specifically had in mind: I have an object that does highly specialized graphics blitting and has a Begin() and End() method (a design also present in DirectX and XNA). Instead...

using(blitter.BlitOperation()) {
    // Do work
}
// Use result

It seems to be more natural and readable, but is it inadvisable, seeing as it uses the IDisposable interface and the using statement for unintended purposes? In other words, would this be on par with overloading an operator in a non-intuitive way?

like image 757
snarf Avatar asked Jul 07 '09 23:07

snarf


2 Answers

This is a perfectly acceptable practice. These are called Factored Types, and the Framework Design Guidelines recommends doing just this.

Basically, if the type wraps an operation with a specific lifetime, using IDisposable and the using statement becomes an appropriate thing to consider.

I actually blogged about this specific topic here, as well.

like image 69
Reed Copsey Avatar answered Oct 01 '22 11:10

Reed Copsey


I recommend against it; my belief is that code is to effectively communicate with the maintainer of the code, not the compiler, and should be written with the maintainer's comprehension in mind. I try to use "using" only to dispose of a resource, typically an unmanaged resource.

I am in a minority. Most people it seems use "using" as a general purpose "I want some cleanup code to run even if an exception is thrown" mechanism.

I dislike this because (1) we already have a mechanism for that, called "try-finally", (2) it uses a feature for a purpose it was not intended for, and (3) if the call to the cleanup code is important, then why isn't it visible at the point where it is called? If it is important then I want to be able to see it.

like image 35
Eric Lippert Avatar answered Oct 01 '22 11:10

Eric Lippert