Introduction
A couple of days ago, I was listening to .NET Rocks while I was jogging, oh yeah you read it write, JOGGING. The episode was named: Venkat Subramaniam Thinks Functionally, nice show, go and get it, I am pretty sure you’ll enjoy the geek out.
There was something I heard Venkat Subramaniam talking about, which captured my attention fully. Something interesting that has to do with cleaning resources when using heavy objects, and by heavy objects I mean objects that use expensive resources which you have to release and dispose of after you finish with them. The usual way of doing this in C# is via using the IDisposable
pattern.
It goes like this: you implement the IDisposable
interface provided by the .NET Framework in your class, and then the user will have to wrap the object with a using
statement or call the Dispose
method explicitly after finishing with the object. The code would be something like:
using System;
namespace IdeasDumb
{
internal class NetHeavyObject : IDisposable
{
public int ProcessHeavyStuff(int value)
{
Console.WriteLine("Processing heavy stuff and leaving resources tangled behind.");
return value * 1000;
}
public void Dispose()
{
Console.WriteLine("Resources has been cleanedup, using Dispose().");
}
}
internal class Program
{
private static void Main(string[] args)
{
using (var obj = new NetHeavyObject())
{
var result = obj.ProcessHeavyStuff(15);
Console.WriteLine("Result = {0}",result);
}
}
}
}
OK, that is good, it works fine, and it is the official pattern used in the .NET Framework. However, you still rely on the user to wrap the object in a using
statement or to call your implemented Dispose
method explicitly. What if the developer forgot to do so?
And here is where Venkat proposes a very interesting way of solving this issue. He is basically solving it by preventing the user from making objects out of the class. What? How can that be useful? How can we call the public
instance methods without an instance of the class? Just bear with me for a moment. The point is that only the class itself can make an object out of itself and use it internally, then cleanup the resources after that. In that case, we don’t have to rely on the developer to cleanup, instead the class does that by itself.
It goes like this:
We make a class VenkatHeavyObject
, which encapsulates a number of useful public
methods, and then we make the constructor private
.
By now, some of you might be thinking Singleton, don’t.
The user will not be able to make any objects out of our class because of the constructor being private
, and that is exactly what we want.
Then, we will provide a static
method named Use
, and it could be a void
for all that matters, that static
method will take an Action<VenkatHeavyObject>
as a parameter. And for the cleanup, we will make a private
method named CleanUp
, which will release the resources.
The Use
method will create a new local VenkatHeavyObject
, and then call the passed Action<VenkatHeavyObject>
and pass the local VenkatHeavyObject
object to it. After that, the Use
method will call CleanUp
method on the local object to clean up its resources and finally returns.
Now, if we want to use that VenkatHeavyObject
class, then we call the Use
method and pass to it a lambda expression that takes a VenkatHeavyObject
object and calls the desired public
method.
Yeah I know it is twisted and it seems hard to get at first. But hopefully when you see the code, you will get it. I might not be the best person to explain it, but I did my best to make it simple.
Here is my implementation for Venkat's idea:
using System;
namespace IdeasDumb
{
internal class VenkatHeavyObject
{
private VenkatHeavyObject()
{
}
public static void Use(Action<venkatheavyobject> action)
{
var instance = new VenkatHeavyObject();
try
{
action(instance);
}
finally
{
instance.CleanUp();
}
}
public int ProcessHeavyStuff(int value)
{
Console.WriteLine("Processing heavy stuff and leaving resources tangled behind.");
return value*1000;
}
private void CleanUp()
{
Console.WriteLine("Resources has been cleaned, internally.");
}
}
internal class Program
{
private static void Main(string[] args)
{
int result = 0;
VenkatHeavyObject.Use((heavyObj) => result = heavyObj.ProcessHeavyStuff(15));
Console.WriteLine("Result = {0}",result);
}
}
}
What a beautiful piece of code. Just amazing, I am not sure if Venkat is the inventor of this pattern or not. Either way, it is awesome and I like it a lot. When I first heard Venkat talk about it, I immediately knew how I was going to implement it in C# using Action<t>
and Lambda, and I couldn’t stop thinking about it while jogging, and once I got home I started coding right away like a maniac, and here is what I got.