apoorv020
apoorv020

Reputation: 5660

Combining foreach and using

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

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

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

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

Upvotes: 44

Views: 17442

Answers (6)

David Neale
David Neale

Reputation: 17038

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

Assigning the variable outside the using block is not normally good practice because the resource would be disposed of but could stay in scope. It would, however, result in clearer code here because you can nest the using statement against the foreach.

Upvotes: 41

Uri Abramson
Uri Abramson

Reputation: 6175

Here's a cleaner syntax:

foreach (ManagementObject obj in result) using (obj)
{
  // do your stuff here
}

Upvotes: 7

Stephen Cleary
Stephen Cleary

Reputation: 456887

ManagementObjectCollection is itself IDisposable...

So it would be...

using (var results = ..)
{
    foreach (var result in results)
    {
        using (result)
        {
            ...
        }
    }
}

Upvotes: 4

Miral
Miral

Reputation: 13075

You can get a nice neat syntax via extension methods and enumerators. First, define this in a public static class somewhere in your code:

public static IEnumerable<ManagementObject> WithDisposal(
                    this ManagementObjectCollection list)
{
    using (list)
    {
        foreach (var obj in list)
        {
            using (obj)
            {
                yield return obj;
            }
        }
    }
 }

... which you can then use with just this:

foreach (var obj in /*get the results*/.WithDisposal())
{
    // ...
}

Though bear in mind that if you use WithDisposal then you won't be able to save any of the objects for future use.

Upvotes: 4

Brian Gideon
Brian Gideon

Reputation: 48959

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();
  }
}

Upvotes: 24

nothrow
nothrow

Reputation: 16178

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.

Upvotes: -1

Related Questions