我可以创建一个通用的方法来释放COM对象吗?

时间:2010-08-29 03:07:02

标签: c# .net com

鉴于以下代码,ReleaseCOMObj()方法是否会释放原始COM对象,还是会隐式创建副本并释放它?

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;
    }
}

更新:将方法更改为静态。有关为什么Object参数不能为ref Object obj的解释,请参阅Passing COM objects as parameters in C#

2 个答案:

答案 0 :(得分:1)

C# parameters are passed by reference

因此,它将释放原始COM对象,但不会将原始变量设置为null

要将原始变量设置为null,请将其更改为ref参数,该参数通过引用传递变量。 (并使用ref关键字)

进行调用

另外,顺便说一下,该方法应为static,因为它不使用this

答案 1 :(得分:1)

如果要将引用设置为null,可以使用通用方法,如:

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

虽然不需要将引用设置为null。无论如何都会释放COM对象。请参阅RealeaseComObject()的文档。您可能还想考虑拨打FinalReleaseComObject()

此外,您可以创建一个实现IDisposable的包装器对象,并使用using块来确保即使存在异常也会释放COM对象。

class ComObjectCleanUp : IDisposable {

    private T obj;

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

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

您的代码变为:

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

虽然我承认这不是很漂亮,特别是考虑到你将使用Office自动化引用的COM对象的数量,但无论如何这都是一个想法。