Click here to Skip to main content
Click here to Skip to main content

RAII (Resource Acquisition Is Initialization) C# Helper Classes

By , 29 Oct 2010
 

Introduction

What the Heck is RAII?

RAII stands for "Resource Acquisition Is Initialization". It is a programming idiom which ensures that there is no resource leak (like lost memory, open handles, dangling critical section monitors, etc.), even if an exception is thrown. For languages like C#, the lost memory is not of an issue, but the problem of "open handles" and "critical section monitors" is equally important.

Some languages provide a mechanism to deterministically and implicitly call one specific function at the end of the lifetime of an object instance (e.g. the destructor in C++). The RAII idiom in C++ takes benefit of that fact and places the "acquisition" of the resource into the constructor (= initialization), and releases the resource in the destructor.

E.g. the C++ auto pointer as well as any guard or sentry classes are implementing the RAII idiom. For more insight, see RAII Idiom.

In C++, a reporting sentry (RAII class) would log the text in its constructor and log again some text in its destructor (that is called when leaving the function body):

// this is C++ use of an RAII class
void f()
{
   ReportSentry reportSentry("function f");
   ...
}

C# does not know this deterministic and implicit destructor call, that's why I explain how I approach this issue in C#.

RAII in the C# World

Coming from a C++ background, I often did apply the RAII idiom. This was not only used for resources but for any kind of action that required symmetric "open-close", "add-remove", "set-reset", "open tag - close tag", "enter critical section - leave critical section", "report start-of-function - report end-of-function", etc. actions - no matter how the control flow left the current scope.

C# provides the well known IDisposable interface. Each class that implements this interface can be considered as "RAII-ready", i.e., one can use an instance of this class in a...

using (...) { ... }

...statement.

But what to do if you have the need of RAII, but no class at hand for the using (...) { ... } statement?

This article shows some simple helper classes that provide an IDisposable wrapper class for an init and a cleanup delegate.

Of course, this is not at all rocket science - actually, it is very simple. It should help to clear up the mist of exception handling involved and focus on the normal control flow.

Using the Code

First, I show the two usages of RAII versus hand crafted side by side.

With RAII support classes Hand crafted
using (var objGuard = new RAIIGuard<int>(
                  () =>objStack.Pop(),
                  (e)=>objStack.Push(e)))
{
    ...
    if (objGuard.Item != 0)
    {
        return;
    }    
    ...
    if (...)
    {
         throw new ...;
    }
    ...
}
int iTaken;
bool bTaken = false;
try
{
    // access the taken object
    iTaken = objStack.Pop();
    bTaken = true; 
    ...
    if (iTaken == 0)
    {
        return;
    }    
    ...
    if (...)
    {
         throw new ...;
    }
    ...
}
finally
{
    if (bTaken)
    {
        objStack.Push(iTaken);
    }
}

I consider the RAII supported approach more legible. If the lambda expressions hurt your eyes, you can always use delegates or methods, e.g.

private int Pop() { return Stack.Pop(); }
private void Push(int i) { Stack.Push(i); }
using (var objGuard = new RAIIGuard<int>(Pop, Push)) 
{
   ...
}

Conveniently, there are two classes to provide that function:

  1. one that has an init action and a cleanup action (e.g. login, logout)
  2. one that has an init function returning an object and a cleanup function taking that object (e.g. login and logout with a session object)
// used for symmetric actions like login, logout
public sealed class RAIIGuard: IDisposable
{
    private Action Cleanup { get; set; }
    public RAIIGuard(Action init, Action cleanup)
    {
        Cleanup = cleanup;
        if (init != null) init();
    }
    void IDisposable.Dispose() { if (Cleanup != null) Cleanup(); }
]
// used for symmetric actions that must pass
// over an object from init to cleanup and that
// need to provide the item to the "using" body
public sealed class RAIIGuard<T>: IDisposable
{
    private Action<T> Cleanup { get; set; }
    public T Item { get; private set; }
    public RAIIGuard(Func<T> init, Action<T> cleanup)
    {
        Cleanup = cleanup;
        Item = (init != null) ? init() : default(T);
    }
    void IDisposable.Dispose() { if (Cleanup != null) Cleanup(Item); }
]

Conclusion

It would still be nice if the committee "guarding" ;-) the C# language could re-consider to implement a native RAII support (e.g. where one can declare a guard as an instance of some kind of "value" type and at the end of the scope, a "Dispose" method is implicitly and deterministically called).

The approach above still requires a certain amount of cooperation by the client where as the pure RAII solution would not need cooperation by the client, i.e., in C#, one can still screw up the RAII idiom by not calling the Dispose() method :-( .

In the meantime, the approach shown above is good enough for me...

History

  • 2010-10-27 Initial version
  • 2010-10-27 Fixed some typos
  • 2010-10-29 Added more background on RAII, explicit implementation of Dispose() (Thanks to Roberto Collina)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Andreas Gieriet
eXternSoft GmbH
Switzerland Switzerland
Member
I feel comfortable on a variety of systems (UNIX, Windows, cross-compiled embedded systems, etc.) in a variety of languages, environments, and tools.
I have a particular affinity to computer language analysis, testing, as well as quality management.
 
More information about what I do for a living can be found at my LinkedIn Profile and on my company's web page (German only).

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionA slight modificationmemberTobiasP14 Feb '12 - 7:19 
This can be a very useful pair of classes. However, the IDisposable.Dispose method description is "Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources" and to use it for something different - calling an action that can do any task, not only release unmanaged resources - is not something I am totally comfortable with. But it can be useful none the less.
 
To make it harder to accidentally not use an instance in a using statement I modified the code slightly. First, I added a finalizer to each of the classes:
        ~RAIIGuard()
        {
            Debug.Fail( "This finalizer should never execute. Please ensure the RAII guard object is disposed correctly." );
 
            ( (IDisposable)this ).Dispose(); // NOTE: Should never execute, but are placed here anyway in case the object is used incorrectly.
        }
I also modified the IDisposable.Dispose methods to ensure the finalizer isn't called if the instance is correctly disposed. Here is the version for RAIIGuard:
        void IDisposable.Dispose()
        {
            if( Cleanup != null )
            {
                Cleanup();
                Cleanup = null;
            }
            GC.SuppressFinalize( this );
        }
Here is the almost identical version for RAIIGuard<T>:
        void IDisposable.Dispose()
        {
            if( Cleanup != null )
            {
                Cleanup( Item );
                Cleanup = null;
            }
            GC.SuppressFinalize( this );
        }
These changes ensure a failure message is displayed in the debug builds (but not release builds) if a RAII guard instance isn't disposed correctly. They also ensure the Cleanup action is called no more than once regardless of how many times an instance is disposed, though disposing an instance more than once that won't happen in a using statement.
AnswerRe: A slight modificationmemberAndreas Gieriet14 Feb '12 - 12:27 
Hello TobiasP,
 
thank you for your input!
 
Please note that my C# implementation of the RAII pattern is never intended as being used for unmanaged resources. I might have to emphasize this in the article. In these rare cases where one has to implement unmanaged resource handling, one would have for sure to encapsulate that in its own class.
 
A Dispose() is normally expected to do disposing only - no reporting, no anything, just dispose.
 
On the other hand, the Dispose() in this RAII implementation welcomes any code that shall be executed while leaving the using block. It is intended to be called in a using block only. Explicitly calling the explicitly implementated Dispose() would require a cast to the interface - which is a read flag in most cases anyways (I regard such code as code smell, especially if not commented why the heck this casting is needed)!
 

There is one intended and right way to use the pattern: using (...) { ... }. All other uses lead to unpredictable behaviour (especially calling Dispose() on the guard).
 
Also with your destructor and calling the Dispose() explicitly, you may cause more harm, since the cleanup code is likely to only work in the given environment of the using block - the app would likely crash here.
 
So, from my point of view, I would stick on the strict pattern: no managed resources, only use in the proper way (using () ..., no tweaking with the guard instance).
 
Regards
 
Andi
GeneralRe: A slight modificationmemberTobiasP14 Feb '12 - 23:56 
Hi.
 
I fully agree that it should be used only in using statements. The modifications I did should not in any way be interpreted to suggest other uses. However, the only reason this class can be used in using statements is because it implements IDisposable and that means it strictly speaking should be expected to "release allocated resources", again quoting MSDN. The RAII usage here assigns a different meaning to its use of the IDisposable interface, so the child class no longer fulfills the promises of the base class (interface). But it can still be very practical if you are aware of the different usage.
 
The RAII pattern here in C# is more convoluted than the RAII pattern in C++ precisely because you have to remember to use using. You cannot force instances of the class to be used only in using statements. Therefore it is much easier to misuse the pattern in C# than it is in C++, and my modifications were made to make it harder to misuse without being detected. In your original code, if you forget to put the instance in a using statement, it will compile and run and you may simply not notice anything wrong. With my modifications, if you forget to put the instance in a using statement, the finalizer will execute when the RAII guard is garbage collected and in debug builds generate an error message at runtime and offer to break into the code in the debugger. My modifications were made only to make it harder to not use the RAII guard in the "one intended and right way", as you wrote, without it being detected. As to whether it should call the dispose method in the finalizer or not, that can be disputed - it's an error situation and if it hadn't been a finalizer I would have thrown an exception there instead of calling Debug.Fail. As it is I think it should fall under undefined behavior but if such a bug do creeps into a release version it might be better to call the cleanup action than to simply ignore it. However that is of course situation dependent. Sometimes it would make more harm than good.
 
Being able to dispose an instance more than once without anything bad happening is not really important, especially as the class implements IDisposable explicitly and is intended to be used only in using statements, but I thought it wouldn't hurt to add it. The documentation for IDisposable.Dispose does specify that you should be able to call the method more than once, but subsequent calls should be ignored.
Generalthanks for sharing - have 5memberPranay Rana17 Jan '11 - 1:24 
thanks for sharing
My blog:http://pranayamr.blogspot.com/
Programming practice

Do vote my articles December 2010
Best C# article of
Best ASP.NET article of

Best overall artic

GeneralMy vote of 5memberWizzard01 Nov '10 - 18:02 
Very nice! Hadn't thought of that Smile | :)
GeneralRAII-guarding fields in vb.netmembersupercat931 Oct '10 - 19:54 
I've come up with a method for RAII-guarding fields in vb.net, which works even if an iDisposable object is created in a initializer or base-class constructor but an exception is thrown before the deepest derived class' constructor completes. The approach would probably work with iDisposables created by the constructor in C#, but not for initializers, since the creators of C# decided to run initializers before constructors (catering to the unusual situation of a constructor calling a virtual method, rather than the scenario of an initializer wanting to define values in terms of the constructed base base object).
 
The object uses a protected constructor which accepts as a parameter a list of iDisposable. The constructor is invoked by a static factory method which creates the list and passes it to the constructor. The creation of any iDisposable created during construction will be wrapped in an RAII method (which in C# would look something like:
T RAII<T>(T thing) {
  DispList.Add(thing); 
  return thing;
}
In VB, such wrappers could be applied to initializations that occur when objects are declared (e.g.
  Dim MyBitmap As RAII(New Bitmap(320,240))
but in C# they would only work for initializations within the constructor.
 
Anyway, the RAII method seems nice as a technique for handling fields that will only be written once, during object construction, and which represent "owned" iDisposable objects. Given a list of iDisposable objects, cleanup is basically a matter of disposing of everything on the list; this can occur either within the object's Dispose method, or in the factory method if an exception is thrown during construction.
GeneralMy vote of 5memberJohn Brett28 Oct '10 - 5:21 
A simple yet effective idea - the best kind.
GeneralRe: My vote of 5memberRoberto Collina28 Oct '10 - 23:42 
I concur. Nothing groundbreaking but I like it all the same. I'm not sure the content warrants an article but I don't mind either. There have been discussions on another popular website whether using IDisposable for this idiom is a good practice or not. I find it elegant, lean and reusable.
 
A minor improvement imho would be explicitly implementing IDisposable. Nit-picking! Smile | :)
GeneralRe: My vote of 5memberAndreas Gieriet29 Oct '10 - 0:53 
Good point. I will adjust the code so that Dispose() is explicitly implemented.
GeneralMy vote of 1memberJohn Simmons / outlaw programmer28 Oct '10 - 5:06 
This article should not have been made available for public consumption. there's not nearly enough here.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 29 Oct 2010
Article Copyright 2010 by Andreas Gieriet
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid