Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Making Disposable Objects the Functional Way

0.00/5 (No votes)
6 Jul 2012 1  
An interesting way of making Disposable (Heavy) objects

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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here