Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I implement the dispose pattern in c# when wrapping an Interop COM Object?

My class contains an object from Interop and calls a method on it which causes it to alloc stuff. It also exposes a method to free that stuff, so I expect I should call this in Dispose():

class MyClass : IDisposable
{
    private DllName.ComClassName comInstance;

    void SomeMethod()
    {
        comInstance = new DllName.ComClassName();
        comInstance.AllocStuff();
    }

    public void Dispose()
    {
        comInstance.FreeThatStuff();
    }
}

Now, I should expand all that to follow the Dispose pattern. I have no other disposable or unmanaged resources to release, so assuming comInstance is managed (isn't that what Interop does, wraps unmanaged into managed?), I think the pattern disolves to:

public void Dispose()
{
    if (comInstance != null)
    {
        comInstance.FreeStuff();
        comInstance = null;
    }
}

Which leaks unless I explicitly call Dispose() on instances of MyClass, which would make the Dispose pattern flawed? So does that mean comInstance must be unmanaged, and the pattern disolves to:

public void Dispose()
{
    DisposeComInstance();
    GC.SuppressFinalize(this);
}

~MyClass()
{
    DisposeComInstance();
}

private void DisposeComInstance()
{
    if (comInstance != null)
    {
        comInstance.FreeStuff();
        comInstance = null;
    }
}

EDIT:

  1. To avoid cluttering my class with the full pattern, could I just seal my class?
  2. How do I know ComClassName (and in general any class) is unmanaged?
like image 934
Sam Avatar asked Jul 28 '09 19:07

Sam


People also ask

How do you implement a Dispose method?

Implement the dispose pattern for a derived class Instead, to clean up a derived class, you provide the following: A protected override void Dispose(bool) method that overrides the base class method and performs the actual cleanup of the derived class. This method must also call the base. Dispose(bool) ( MyBase.

How do I call a Dispose method?

public void Dispose() { Dispose(disposing: true); // This object will be cleaned up by the Dispose method. // Therefore, you should call GC. SuppressFinalize to // take this object off the finalization queue // and prevent finalization code for this object // from executing a second time.

When should you implement a Dispose?

If you access unmanaged resources (e.g. files, database connections etc.) in a class, you should implement IDisposable and overwrite the Dispose method to allow you to control when the memory is freed.

Why we need to implement Dispose method?

Dispose improves performance and optimizes memory by releasing unmanageable objects and scarce resources, like Graphics Device Interface (GDI) handles used in applications with restricted Windows space. The Dispose method, provided by the IDisposable interface, implements Dispose calls.


1 Answers

Ultimately you want this kind of pattern:

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

~MyClass()
{
    Dispose(false);
}

private void Dispose(bool disposing)
{
    if (disposing)
    {
        // Dispose of disposable objects here

    }

    // Other unmanaged cleanup here which will be called by the finalizer
    if (comInstance != null)
    {
         comInstance.FreeStuff();
         comInstance = null;
    }

    // Call base dispose if inheriting from IDisposable class.
    base.Dispose(true);
}

For a great article on why, check out Implementing IDisposable and the Dispose pattern properly.

like image 197
womp Avatar answered Nov 14 '22 21:11

womp