我被 .Net 1.1 应用程序困住了(即我现在无法使用 2.0 中的泛型好东西),并且我试图优化代码的某些部分。由于它处理大量需要释放的运行时可调用包装器,我最终创建了一个实用程序方法,该方法循环直到所有引用都被释放。该方法的签名是:
void ReleaseObject(object comObject)
释放所有 comObject 后,我调用 GC.Collect 和 GC.WaitForPendingFinalizers(不要问 - 任何处理 Office 互操作的人都知道)。
和往常一样,我遇到了一个极端情况 - 如果我在 GC.Collect 调用之前没有将相应的托管引用分配给 null,它就无法正确清理。
所以,我的代码如下所示:
ReleaseObject(myComObject);
myComObject = null;
GC.Collect()
...
由于有一堆xxx=null,我决定将其放入util方法中,但是由于通过引用传递和传递引用参数之间存在差异,显然我必须将方法更改为:
void ReleaseObject(out object comObject)
{
//do release
comObject = null;
}
并将调用者编辑为:
MyComClass myComObject = xxxx;
ReleaseObject(out myComObject);
此操作失败并显示消息:“无法从 'out MyComClass' 转换为 'out object'”
虽然我可以想到为什么这可能是一个问题(即从对象到 MyComClass 的反向转换不是隐式的,并且不能保证该方法会做什么),但我想知道是否有解决方法,或者我需要保留我的数百个空值分配。
注意:我有一堆不同的 COM 对象类型,这就是为什么我需要一个“对象”参数,而不是类型安全的参数。
最佳答案
为什么调用方法比直接将变量设置为 null 更好?它们都是单线调用,后者要简单得多。
不过,您首先需要将它们设置为空,这听起来确实很奇怪。这些是静态变量还是实例变量,其值需要比其包含对象更早释放?如果变量只是一个局部变量,无论如何都会超出范围,那么将其设置为 null 应该不会有任何区别(在发布中)。
RCW 没有实现 IDisposable 吗?如果是这样,调用 Dispose(最好通过 using 语句)将是最好的选择。
(经过评论讨论。)
这些是局部变量,稍后在方法中不会引用。这意味着垃圾收集器将意识到它们不需要被视为“根”引用 - 因此将它们设置为 null 应该不会有任何区别。
但是,要直接回答最初的问题:不,除非方法参数具有完全相同的类型,否则您不能通过引用传递变量,所以您在这里运气不好。 (使用泛型这是可能的,但您说过您仅限于 .NET 1.1。)
关于c# - 使用 "ref"和/或 "out"作为对象类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/244826/