Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# foreach与using的结合_C#_Foreach_Idisposable_Using - Fatal编程技术网

C# foreach与using的结合

C# foreach与using的结合,c#,foreach,idisposable,using,C#,Foreach,Idisposable,Using,我正在迭代ManageObjectCollection(它是WMI接口的一部分) 然而,重要的是,以下代码行: foreach (ManagementObject result in results) { //code here } 关键是ManageObject还实现了IDisposable,所以我想把“result”变量放在using块中。你知道如何做到这一点,而不会变得太怪异或复杂吗 foreach (ManagementObject result in results) usi

我正在迭代ManageObjectCollection(它是WMI接口的一部分)

然而,重要的是,以下代码行:

foreach (ManagementObject result in results)
{
    //code here
}
关键是ManageObject还实现了IDisposable,所以我想把“result”变量放在using块中。你知道如何做到这一点,而不会变得太怪异或复杂吗

foreach (ManagementObject result in results)
using(result)
{
    //code here
}
使用块将变量分配到
之外通常不是一种好的做法,因为资源将被释放,但可以保留在范围内。但是,它会在这里产生更清晰的代码,因为您可以使用
语句将
嵌套在
foreach

编辑: 正如在另一个答案中指出的那样,
ManagementObjectCollection
还实现了
IDisposable
,因此我使用
块将其添加到


无需将
ManagementObjectCollection
放在using语句中。
foreach
将调用枚举器上的
Dispose()

它看起来很奇怪-在数组上迭代并处理它包含的每个对象。如果您真的想这样做,请使用

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

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

这正是
使用
语句所做的。

ManagementObjectCollection
本身就是
IDisposable

所以这将是

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

您可以执行以下操作

foreach (ManagementObject result in results)
{
  using (result)
  {
    // Your code goes here.
  }
}
关于C#的巧妙之处在于不同的语言构造如何共享作用域代码块。这意味着您可以执行以下操作来消除嵌套

foreach (ManagementObject result in results) using (result)
{
  // Your code goes here.
}
了解
foreach
构造也将在目标
IEnumerator
上调用
Dispose
,这也很有用。上面的代码相当于

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

您可以通过扩展方法和枚举器获得一个漂亮整洁的语法。首先,在
公共静态类
的代码中的某个地方定义它:

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

但是请记住,如果您将
与Disposition一起使用
,则无法保存任何对象以供将来使用。

这里有一个更简洁的语法:

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

我认为Dispose方法是由一个站点调用的,其中“result”对象createdNo,Dispose可以在任何地方调用。foreach会自动调用Enumerable上的Dispose,如果它是IDisposable,那么首先使用unnecessary@Alexanderforeach将对枚举器调用Dispose,该枚举器将由ManagementObjectCollection GetEnumerator()方法返回。不会对ManagementObjectCollection对象调用Dispose。如果//此处的代码引发异常,会发生什么?!结果中的所有剩余对象将不会被处理,并且您存在内存泄漏!!这不会对每个
ManagementObject
调用Dispose(),只对
ManagementObjectCollection
本身调用。非常奇怪的是,它会对
ManagementObjectCollection
foreach
循环中使用的
IEnumerator
调用
Dispose
。我喜欢这样。您甚至可以使用类型约束将其泛型为
IDisposable
。您可以,但这绝对是一个特例。通常,处置一次性对象的集合也应处置其包含的对象。(为此,我在代码中定义了一个generic
DisposableList
)。还有一个警告——只有在实际完全遍历返回的枚举时,才会处理所有内容。如果中途停止,则集合仍将被释放,但尚未查看的任何对象将不会被释放。当然,这也适用于这里发布的大多数其他答案。因为这正是“using语句所做的”,所以你不应该这样做。
foreach (ManagementObject obj in result) using (obj)
{
  // do your stuff here
}