tags:

views:

32

answers:

2

Given the following code, will the ReleaseCOMObj() method release the original COM object, or will it implicitly create a copy and release that?

private void TestRelease()
{
    Excel.Workbook workbook = excel.ActiveWorkbook;
    // do stuff
    ReleaseComObj(workbook);
}

private static void ReleaseComObj(Object obj)
{
    if (obj != null)
    {
        Marshal.ReleaseComObject(obj);
        obj = null;
    }
}

Update: Changed method to static. See Passing COM objects as parameters in C# for an explanation as to why the Object parameter cannot be ref Object obj.

+1  A: 

C# parameters are passed by reference.

Therefore, it will release the original COM object, but it won't set the original variable to null.

To set the original variable to null, change it to a ref parameter, which passes a variable by reference. (and call it with the ref keyword)

Also, by the way, the method should be static, since it doesn't use this.

SLaks
"it will release the original COM object, but it won't set the original variable to null." - that's the key piece of information that I was looking for.
Nick Hebb
+1  A: 

If you want to set the reference to null you can use a generic method like:

 private static void ReleaseComObj<T>(ref T obj) where T:class  {
        if (obj != null) {
            Marshal.ReleaseComObject(obj);
            obj = null;
        }
    }

Although setting the reference to null isn't needed. The COM object will be released in any case. See the documentation for RealeaseComObject(). You may also want to consider calling FinalReleaseComObject().

Also you could create a wrapper object that implements IDisposable and use a using block to ensrue the COM object is released even if there is an exception.

class ComObjectCleanUp : IDisposable {

    private T obj;

    public ComObjectCleanUp(T obj) {
        this.obj = obj;
    }

    public void Dispose() {
        if (obj != null)
            Marshal.FinalReleaseComObject(obj);
    }
}

And your code becomes:

private void TestRelease()
{
    Excel.Workbook workbook = excel.ActiveWorkbook;
    using (var c = new ComObjectCleanUp(workbook))
    {
        // do stuff
    }
}

Although I will admit that isn't very pretty, especially considering the number of COM objects you will reference using Office automation, but it's an idea anyway.

shf301
That's a clever solution, but in the end I just went with a code snippet w/ shortcut:if ($obj$ != null) { Marshal.ReleaseComObject($obj$); }.
Nick Hebb