views:

125

answers:

4

I'm iterating over a ManageObjectCollection.( which is part of WMI interface).

However the important thing is, the following line of code. :

foreach (ManagementObject result in results)
{
    //code here
}

The point is that ManageObject also implements IDisposable, so I would like to put "result" variable in a using block. Any idea on how to do this, without getting too weird or complex?

+5  A: 
using(ManagementObjectCollection results = /*get the results*/)
foreach (ManagementObject result in results)
using(result)
{
    //code here
}

It's not normally good practice to assign the variable outside the using block because the resource would be disposed but could stay in scope. It would, however, result in clearer code here because you can nested the using statement against the foreach.

EDIT: As pointed out in another answer, ManagementObjectCollection also implements IDisposable so I have added that into a using block.

David Neale
I think Dispose method has be invoked by a site where "result" object where created
Arseny
No, Dispose can be called anywhere.
Cylon Cat
+1  A: 

It will look weird - iterating over array and disposing each of the objects it contains. If you really want to do this, use

foreach (ManagementObject result in results)
{
    try {
        // code here
    }
    finally {
        result.Dispose();
    }
}

/* do not forget to, or to not reuse results!
results = null; 
results.Clear();
*/

which is exactly what using statement does.

Yossarian
+2  A: 

ManagementObjectCollection is itself IDisposable...

So it would be...

using (var results = ..)
{
    foreach (var result in results)
        ...
}
Stephen Cleary
This would not call Dispose() on each `ManagementObject`, only on the `ManagementObjectCollection` itself.
David Neale
To be very padantic it would call `Dispose` on both the `ManagementObjectCollection` and the `IEnumerator` used in the `foreach` loop.
Brian Gideon
+1  A: 

You could do the following.

foreach (ManagementObject result in results)
{
  using (result)
  {
    // Your code goes here.
  }
}

The neat thing about C# is how different language constructs can share scoped code blocks. That means you could do the following to eliminate the nesting.

foreach (ManagementObject result in results) using (result)
{
  // Your code goes here.
}

It is also useful to know that the foreach construct will call Dispose on the target IEnumerator as well. The code above would be equivalent to.

IEnumerator enumerator = results.GetEnumerator()
try
{
  while (enumerator.MoveNext())
  {
    ManagementObject result = (ManagementObject)enumerator.Current;
    IDisposable disposable = (IDisposable)result;
    try
    {
      // Your code goes here.
    }
    finally
    {
      disposable.Dispose();
    }
  }
}
finally
{
  IDisposable disposable = enumerator as IDisposable;
  if (disposable != null)
  {
    disposable.Dispose();
  }
}
Brian Gideon