views:

107

answers:

3

I'm building a class that derives from Stream to wrap a COM IStream. However I've come across an issue where I need to release the COM IStream deteministically.

Ok so that's easy just use Marshal.ReleaseComObject in the Dispose method. However I'm not sure its that simple. The Stream base class already has an protected virtual method Dispose(boolean). Here is my first idea:-

    ~ComStreamWrapper()
    {
        if (!_Disposed)
        {
            iop.Marshal.FreeCoTaskMem(_Int64Ptr);
            iop.Marshal.ReleaseComObject(_IStream);
        }
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);

        if (!_Disposed)
        {
            if (disposing)
            {
                iop.Marshal.FreeCoTaskMem(_Int64Ptr);
                iop.Marshal.ReleaseComObject(_IStream);
            }
            _Disposed = true;
        }
    }

You'll notice there isn't an implementation of Dispose() itself. I'm currently making the asssumption that the existing implementation on Stream does what I need it to. That is calling Diposing(true) and GC.SuppressFinalize. Is this assumption faulty?

Have I missed something? Is there a better approach? You see more of the basic class in this answer to an ealier question.

+2  A: 

I'm currently making the asssumption that the existing implementation on Stream does what I need it to. That is calling Diposing(true) and GC.SuppressFinalize. Is this assumption faulty?

That's exactly what it does. Well, it calls Close, which is:

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

A general tip when you want a definitive answer to what some standard class really does, open it in Reflector and look at the C# disassembly of it.

Daniel Earwicker
A: 

This dispose method:

  protected virtual void Dispose(bool disposing)

is a common pattern. I would assume that every Dispose method in the Framework looks like this (whenever the class can be derived):

public void Dispose()
{
  Dispose(true);
  GC.SuppressFinalize(this);
}
Stefan Steinegger
+1  A: 

Overriding the Disposing method and calling it from the finalizer will get the job done. Note that you'll want to release the resources in both cases. Thus:

~ComStreamWrapper()
{
    Dispose(false);
}

protected override void Dispose(bool disposing)
{
    base.Dispose(disposing);
    if (!_Disposed)
    {
        iop.Marshal.FreeCoTaskMem(_Int64Ptr);
        iop.Marshal.ReleaseComObject(_IStream);
        _Disposed = true;
    }
}
Hans Passant
The bas class already has a destructor (Finalizer).
Henk Holterman
The Stream class is abstract and doesn't have a finalizer.
Hans Passant
It seems you're right, my mistake.
Henk Holterman
@Hans: Lovely, jubbely thanks (again).
AnthonyWJones