Сочетание foreach и использование - PullRequest
29 голосов
/ 09 июня 2010

Я перебираю коллекцию ManageObjectCollection (которая является частью интерфейса WMI).

Однако важна следующая строка кода. :

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

Дело в том, что ManageObject также реализует IDisposable, поэтому я хотел бы поместить переменную "result" в блок использования. Есть идеи, как это сделать, не становясь слишком странным или сложным?

Ответы [ 6 ]

25 голосов
/ 09 июня 2010
foreach (ManagementObject result in results)
using(result)
{
    //code here
}

Обычно не рекомендуется назначать переменную вне блока using, поскольку ресурс будет удален, но может остаться в области видимости.Однако это приведет к более ясному коду, поскольку вы можете вкладывать оператор using против foreach.

EDIT: Как указано в другом ответе, ManagementObjectCollection также реализует IDisposable поэтому я добавил это в using блок.

Нет необходимости помещать ManagementObjectCollection в операторе using.foreach вызовет Dispose() на счетчике.

18 голосов
/ 09 июня 2010

Вы можете сделать следующее.

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

Отличительной особенностью C # является то, как различные языковые конструкции могут совместно использовать блоки кода области. Это означает, что вы можете сделать следующее, чтобы устранить вложение.

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

Также полезно знать, что конструкция foreach также вызовет Dispose для цели IEnumerator. Код выше будет эквивалентен.

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();
  }
}
4 голосов
/ 06 апреля 2011

Вы можете получить хороший аккуратный синтаксис с помощью методов расширения и перечислителей.Во-первых, определите это в public static class где-нибудь в вашем коде:

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

..., который затем можно использовать только с этим:

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

Хотя имейте в виду, что есливы используете WithDisposal, тогда вы не сможете сохранить объекты для дальнейшего использования.

2 голосов
/ 09 июня 2010

ManagementObjectCollection само по себе IDisposable ...

Так было бы ...

using (var results = ..)
{
    foreach (var result in results)
    {
        using (result)
        {
            ...
        }
    }
}
1 голос
/ 25 июня 2013

Вот более чистый синтаксис:

foreach (ManagementObject obj in result) using (obj)
{
  // do your stuff here
}
0 голосов
/ 09 июня 2010

Это будет выглядеть странно - перебирать массив и удалять каждый из содержащихся в нем объектов. Если вы действительно хотите это сделать, используйте

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

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

Это именно то, что делает оператор using.

...