鉴于以下代码,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#。
答案 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对象的数量,但无论如何这都是一个想法。