Search code examples
c#raii

Is RAII safe to use in C#? And other garbage collecting languages?


I was making an RAII class that takes in a System.Windows.Form control, and sets its cursor. And in the destructor it sets the cursor back to what it was.

But is this a bad idea? Can I safely rely that the destructor will be called when objects of this class go out of scope?


Solution

  • This is a very, very bad idea.

    Finalizers are not called when variables go out of scope. They're called at some point before the object is garbage collected, which could be a long time later.

    Instead, you want to implement IDisposable, and then callers can use:

    using (YourClass yc = new YourClass())
    {
        // Use yc in here
    }
    

    That will call Dispose automatically.

    Finalizers are very rarely necessary in C# - they're only required when you directly own an unmanaged resource (e.g. a Windows handle). Otherwise, you typically have some managed wrapper class (e.g. FileStream) which will have a finalizer if it needs one.

    Note that you only need any of this when you have resources to be cleaned up - most classes in .NET don't implement IDisposable.

    EDIT: just to respond to the comment about nesting, I agree it can be a bit ugly, but you shouldn't need using statements very often in my experience. You can also nest usings vertically like this, in the case where you've got two directly adjacent ones:

    using (TextReader reader = File.OpenText("file1.txt"))
    using (TextWriter writer = File.CreateText("file2.txt"))
    {
        ...
    }