Search code examples
c#foreachcomidisposablercw

Proper way to Dispose of IDisposable COM Object Wrappers After foreach Loop


foreach loops call .dispose() on objects which implement IDisposable automatically. It's a nice feature, but let's say you had the following function:

public COMWrapper GetCOMWrapperByName(string COMWrapperName)
{
    List<COMWrapper> COMWrapperList = GetCOMWrappersFromPlace();

    foreach(COMWrapper cw in COMWrapperList)
    {
        if(cw.name == COMWrapperName)
            return cs;
    }
}

And that COMWrapper's .dispose() method released it's associated COM Object.

As I understand it, the foreach loop would dispose of each COMWrapper at the end of the loop, but then leave the matched COMWrapper since it was returned before reaching the end of the statement.

This becomes a problem, however, for the COMWrapper references left in the COMWrapperList list, as half of them have had their underlaying COM Object RCW wrappers removed without themselves being disposed of. Worse, the REMAINING half of the list has totally unmanaged COM Objects now floating in the ether, and since the COMWrapper objects they exist in haven't been disposed of, it becomes very difficult to traverse the List and call .dispose() appropriately in a finally statement (we don't, after all, want to release COM Objects twice).

Is it possible to determine if a COM Object has been released without catching a ObjectDisposedException exception? Is there a better way to dispose of the remaining COM Objects and their wrappers? Or maybe I'm absolutely misreading this situation and need to reevaluate my base understanding of COM Objects, what am I doing wrong?


Solution

  • foreach doesn't dispose of all of the objects in the sequence being iterated. It only disposes of the IEnumerator object that provides you with the objects being iterated over.