Saturday, December 6, 2008

C++/CLI equivalent of C# using statement for automatic disposing.

A common practice, and a good one, in C# is to wrap a class that implements the IDisposable interface in a using block like so:

using (FileStream filestream = new FileStream("MyFile.txt", FileMode.Open, FileAccess.Read))
{
// Perform some file operations
}

The code will automatically call Dispose one the filestream instance even if an exception is throw inside the code block. Dispose is typically used to free resources immediately instead of waiting for the garbage collector to make it’s pass and clean up the class. In situations where you are creating and deleting a lot of objects that may contain handles or unmanaged buffers internally this can keep system resource use down. So how is this accomplished in C++/CLI? There is no using statement in C++/CLI. It turns out that it’s supported in what I think is a more elegant way than C#. For starters to define a class in C++/CLI that implements the IDisposable interface you don’t have to actually inherit IDisposable explicitly you simply define a destructor for the class like so:

public ref class MyClass
{
public:
MyClass(void)
{
}

virtual ~MyClass(void)
{
//Free resources here. This is the IDisposable.Dispose(); equivalent
}
};

The above C++/CLI code would emit the IDisposable interface automatically. To call the Dispose method in C++/CLI you delete the object just like you naturally would in C++:

int main(array<System::String ^> ^args) 
{
MyClass ^ myclass = gcnew MyClass();

//Do some stuff with myclass

delete myclass; //Dispose gets called

return 0;
}

So far we have seen how to implement IDisposable and how to explicitly call Dispose in C++/CLI. Now I will show you the C++/CLI equivalent of C#’s using statement block. This too is very elegant in C++/CLI. To do this we allocate the class on the stack instead of the heap like so:

int main(array<System::String ^> ^args) 
{
MyClass myclass;

//Do some stuff with myclass

//When myclass goes out of scope Dispose will be called.

return 0;
}

The above is the same as the using statement block in C#. The Dispose method is automatically called once myclass goes out of scope. Notice the ^ is missing from the declaration. This puts the class on the stack instead of the heap. When the class is popped off the stack at the end of the function the Dispose method is called for the class. OK all finished right? Wrong. What if MyClass has no public constructor and the only way to create it is by calling a static method that returns a handle to MyClass (i.e. MyClass ^)? A good example of this is the Graphics class. In C# we can do something like this:

using (Graphics graphics = Graphics.FromImage(img)) 
{
//Do stuff
//Dispose is called on graphics when we exit this code block
}

It’s not possible to allocate the Graphics object on the stack in C++/CLI because there is no public constructor for it and the “From” methods return a Graphics ^ which puts the instance on the heap instead of the stack. So how do we accomplish the same result as above then? In my first C++/CLI example where I called delete ont the myclass instance I didn’t exactly present the best practice for C++/CLI code when dealing with disposable objects actually. I did that on purpose so I could show it here:

Graphics ^ graphics = Graphics::FromImage(img); 

try
{
//Do stuff
//Dispose is called on graphics when we exit this code block
}
finally
{
delete graphics;
}

By using the try..finally code block we accomplish the same thing as the C# code. So that’s it. I think C++/CLI does IDisposable in a elegant way. What do you think?


No comments: