We’ve already discussed RAII in C++, now it’s time to see how we implement the same pattern in C#. We don’t manage our memory in C#, however we still need to manage other resources, like network and database conections, files and mutexes. In C++, whenever control leaves a block, the local objects defined in that block are destroyed. In C# this is not the case because the runtime uses garbage collection to manage memory. This means that the runtime periodically looks for objects that are no long referenced and deletes those that it finds. So, unfortunately, we cannot use the same trick manage resources.
In order to guarantee that a resource is released in C# we can use a finally
block like so:
// acquire a resource
try
{
// use resource and do other stuff as well
}
finally
{
// release resource
}
A finally
block will be executed whenever control leaves the try block, either because it reaches the end of the block, it reaches a return statement of an exception is thrown.
We can also encapsulate resource management with a class like in C++. In C# we normally do this by implementing the IDisposable
interface. The IDisposable
interface looks like this:
interface IDisposable
{
void Dispose();
}
We acquire the resource in the constructor and we release the resource in the Dispose method.
class ResourceHolder : IDisposable
{
public ResourceHolder()
{
// acquire resource here
}
public void Dispose()
{
// release resource
}
}
The Dispose
method of our ResourceHolder
must be called. It does not happen automatically like a destructor in C++. We can combine a class implementing IDisposable
with the finally block like this:
var holder = ResourceHolder()
try
{
// use resource and do other stuff as well
}
finally
{
holder.Dispose();
}
In fact, this pattern is so useful that some syntactic sugar exists for it, the using statement
.
using(var holder = ResourceHolder())
{
// use resource and do other stuff as well
}
The above code is exactly equivalent to our previous code example with an explicit finally
block. Whenever control exits the using block, the Dispose
method of the object declared inside the using statement is called.
RAII is a great example of something that ends up being more complicated in C# than it is in C++. Usually, things are easier in C#!