Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.Net WMI classes - which ones do I have to dispose?

If I am using a ManagementObjectSearcher, I can easily wrap it in a using block:

using (var searcher = new ManagementObjectSearcher(scope, query))
{
    // ...
}

It is also easy to dispose the collection returned from the searcher, due to the fact that foreach automatically calls dispose on the enumerator:

using (var searcher = new ManagementObjectSearcher(scope, query))
{
    foreach(ManagementObject mo in searcher.Get())
    {
        // ...
    }
}

But ManagementObject also implements IDisposable:

using (var searcher = new ManagementObjectSearcher(scope, query))
{
    foreach(ManagementObject mo in searcher.Get())
    {
        // ...

        mo.Dispose(); // ?
    }
}
  • Do I have to dispose each ManagementObject instance returned in this scenario?
  • If I do, how do I make it exception safe?
  • Is there a way I can still use Linq in this scenario (and still properly call Dispose)? Especially with constructions like searcher.Get().First()?

Edit: A few more related questions:

  • Do I also have to call Dispose on the search result collection?
  • How about the searcher?

They both also implement their own IDisposable method, though it seems like the searcher only inherits the Dispose implementation from Component; it doesn't add its own dispose behavior.

like image 824
Merlyn Morgan-Graham Avatar asked Jul 10 '11 05:07

Merlyn Morgan-Graham


1 Answers

ManagementObject inherits from System.ComponentModel.Component and you should call Dispose explicitly for all inherited from Component objects. You can use LINQ methods with your own predicates which invokes Dispose itself:

var first = searcher.Get().First(x =>
                {
                    bool result = Satisfy(x);

                    if (!result)
                    {
                        x.Dispose();
                    }

                    return result;
                });

This code is equivalent to:

ManagementObject first = null;

foreach (var element in searcher.Get())
{
    if (Satisfy(element))
    {
        first = element;
        break;
    }
    else
    {
        element.Dispose();    
    }
}

if (first == null)
{
    throw new InvalidOperationException("No match");
}

Where Satisfy is your own method.

like image 84
oxilumin Avatar answered Nov 02 '22 12:11

oxilumin