Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using IDisposable through inheritance

I am using inheritance and trying to understand the best way of using IDisposable. Below is an example of my base class.

I understand that if I have a class (lets call in MyChild) that inherits from MyBase class even if MyChild doesn't implement IDisposable that if MyChild is initialised the Dispose method will be executed (believe I'm correct in saying that) if used like below,

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

What I would like to know though is say I have an object in MyChild class that I want to make sure is disposed of. Would I have to implement the IDisposable interface and have pretty much the same code that I have in MyBase class or can I make use of the code in MyBase class? I'm guessing that's why there is a protected virtual Dispose method in MyBase class?

My Base Class

 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);
        }
 }
like image 529
mHelpMe Avatar asked Jul 05 '26 01:07

mHelpMe


2 Answers

The void Dispose(bool disposing) is protected virtual for a reason. You are meant to override it (and call the base version).

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

        base.Dispose(disposing);
    }
}
like image 194
GSerg Avatar answered Jul 07 '26 15:07

GSerg


You just have to override the Dispose(bool) method in the child class to add any other disposals you want.

However, this is side-stepping the real issue - what you're doing is somewhat unnecessary and kind of dangerous dangerous:

The lesson here is: If you’re tempted to call “Marshal.ReleaseComObject”, can you be 100% certain that no other managed code still has access to the RCW? If the answer is ‘no’, then don’t call it. The safest (and sanest) advice is to avoid Marshal.ReleaseComObject entirely in a system where components can be re-used and versioned over time.

The COM wrapper .NET builds for you is safe and managed, and you should avoid any explicit disposals unless absolutely necessary. Even the documentation of Marshal.ReleaseComObject gives a few good reasons to avoid this:

A more serious error may occur if a call to the RCW is executing when the RCW is released. In this case, there is a good chance that the thread making the call will cause an access violation. However, process memory may become corrupted, and the process may continue to run until it fails for reasons that are very difficult to debug.

...

Therefore, use the ReleaseComObject only if it is absolutely required. If you want to call this method to ensure that a COM component is released at a determined time, consider using the FinalReleaseComObject method instead.

Finally, you have to understand that whatever you do on your side, there's no guarantee that the COM object will do any deterministic disposal anyway. This is up to the COM object, not the runtime callable wrapper in .NET. All you do is say "there's no more references to this COM object". Well, it should be obvious that that's pretty much the same thing that happens when the local gets out of scope, and is eventually garbage collected.

like image 32
Luaan Avatar answered Jul 07 '26 15:07

Luaan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!