2010-06-09 38 views
24

我遍歷一個ManageObjectCollection(它是WMI接口的一部分)。結合使用foreach和使用

但重要的是,下面這行代碼。 :

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

問題是ManageObject也實現了IDisposable,所以我想把「result」變量放在一個using塊中。有關如何做到這一點的想法,不要太奇怪或複雜?

回答

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

這不是一般好的做法變量分配using塊外,因爲資源會被佈置,但可以留在範圍之內。但是,它會導致代碼更清晰,因爲您可以將using語句與foreach嵌套。

編輯: 作爲另一個答案指出,ManagementObjectCollection還實現IDisposable所以我補充說成using塊。

不需要在使用語句中放置ManagementObjectCollectionforeach將在枚舉器上調用Dispose()

+0

我覺得Dispose方法已經在那裏建立 – Arseny 2010-06-09 11:24:42

+0

無,處置任何地方都可以稱爲一個網站,「結果」的對象被調用。 – 2010-06-09 11:47:00

+1

foreach自動調用Disume Enumerable,如果它是IDisposable,那麼首先使用不必要的 – Alexander 2013-06-06 05:28:27

-1

它看起來很奇怪 - 遍歷數組並處理它包含的每個對象。如果你真的想這樣做,使用

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聲明一樣。

+1

因爲這是「正是使用聲明所做的」,所以你不應該這樣做。 – CertifiedCrazy 2018-01-09 17:14:55

2

ManagementObjectCollection本身IDisposable ...

因此,這將是...

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

這不會在每個'ManagementObject'上調用Dispose(),只會在'ManagementObjectCollection'本身上調用Dispose()。 – 2010-06-09 11:35:15

+0

爲了非常無聊,它會在'foreach'循環中的'ManagementObjectCollection'和'IEnumerator'上調用'Dispose'。 – 2010-06-09 13:02:27

13

你可以做到以下幾點。

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

你可以通過擴展方法和枚舉器得到一個很好的整齊語法。首先,在你的代碼在某處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然後你贏了將無法保存任何對象以供將來使用。

+0

我喜歡這個。你甚至可以使用'IDisposable'對類型約束進行泛化。 – Chad 2013-04-11 19:09:56

+1

你可以,但這絕對是一個特例。通常處理一次性物品的集合也應該處理其包含的物品。 (爲了這個目的,我在代碼中定義了一個通用的'DisposableList')。 – Miral 2013-04-12 02:44:07

+1

還有一個警告 - 如果你真的完全遍歷返回的枚舉,它將只處理所有事情。如果你在中途停下,那麼這個藏品仍然會被丟棄,但是你還沒有看過的任何物品都不會。當然,這也適用於這裏發佈的大多數其他答案。 – Miral 2013-06-05 07:20:45

1

這裏有一個更清晰的語法:

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