C# foreach与using的结合
我正在迭代ManageObjectCollection(它是WMI接口的一部分) 然而,重要的是,以下代码行: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
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
。您可以,但这绝对是一个特例。通常,处置一次性对象的集合也应处置其包含的对象。(为此,我在代码中定义了一个genericDisposableList
)。还有一个警告——只有在实际完全遍历返回的枚举时,才会处理所有内容。如果中途停止,则集合仍将被释放,但尚未查看的任何对象将不会被释放。当然,这也适用于这里发布的大多数其他答案。因为这正是“using语句所做的”,所以你不应该这样做。
foreach (ManagementObject obj in result) using (obj)
{
// do your stuff here
}