通过继承使用idisable

本文关键字:idisable 继承 | 更新日期: 2023-09-27 18:11:52

我正在使用继承,并试图理解使用IDisposable的最佳方法。下面是我的基类的一个例子:

我明白,如果我有一个类(让在MyChild中调用)继承自MyBase类,即使MyChild不实现IDisposable,如果MyChild被初始化,Dispose方法将被执行(相信我是正确的),如果像下面这样使用,

using(MyChild chl = new MyChild) {// some code};

我想知道的是说我在MyChild类中有一个对象,我想确保它被处理掉。我是否必须实现IDisposable接口并拥有与MyBase类中相同的代码,或者我可以使用MyBase类中的代码?我猜这就是为什么在MyBase类中有一个受保护的虚拟处置方法?

我的基类

 public class MyBase : IDisposable
 {
        // variables & methods declared here etc
        public void Dispose()
        {
            Dispose(true);
        }
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (myObj != null) releaseObject(myObj);
            }
        }
        private static void releaseObject(object obj)
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
        }
 }

通过继承使用idisable

void Dispose(bool disposing)protected virtual是有原因的。您应该重写它(并调用基本版本)。

public class MyChild : MyBase
{
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            // Dispose Child's objects
        }
        base.Dispose(disposing);
    }
}

你只需要在子类中重写Dispose(bool)方法来添加你想要的任何其他处置。

然而,这回避了真正的问题——你正在做的事情有些不必要,而且有点危险。

这里的教训是:如果你想叫"元帅"。,你能100%确定没有其他托管代码仍然访问RCW吗?如果答案是否定的,那就别打了。最安全(也是最理智)的建议是避免使用Marshal。在一个系统中完全释放ecomobject,在这个系统中组件可以随着时间的推移被重用和版本化。

. net为您构建的COM包装器是安全且受管理的,除非绝对必要,否则您应该避免任何显式的处置。甚至还有马歇尔的文件。ReleaseComObject给出了一些很好的理由来避免这种情况:

当RCW被释放时,如果对RCW的调用正在执行,可能会发生更严重的错误。在这种情况下,执行调用的线程很有可能导致访问冲突。但是,进程内存可能会损坏,并且进程可能会继续运行,直到由于难以调试的原因而失败。

因此,只有在绝对需要时才使用ReleaseComObject。如果你想调用这个方法来确保COM组件在确定的时间被释放,可以考虑使用FinalReleaseComObject方法。

最后,您必须理解,无论您在您这边做什么,都不能保证COM对象将执行任何确定性处置。这取决于COM对象,而不是. net中运行时可调用的包装器。你所要做的就是说"不再有对这个COM对象的引用"。很明显,这与局部超出作用域并最终被垃圾收集时发生的事情几乎相同。