2011-12-01 79 views
6

因此,代碼分析告訴我Enumarble.Where(this ...)正在返回一個WhereListIterator<T>的實例,該實例在.NET框架內(看起來)是一個內部類型,它實現了IDisposableCoverity,Enumerable.Where(this ...)和IDisposable

Coverity不喜歡IDisposable的未處置,因此建議我處置所述實例。很明顯,我不能在沒有進行某種類型檢查的情況下處理該實例,因爲Enumerable.Where(this ...)據說返回IEnumerable<T>,而不是從IDisposable中刪除。

我的問題是這樣的:.net期望我能夠處理WhereListIterator<T>,或者迭代器是否處理自己(比如每次枚舉後)。如果我不希望處理它,那麼接口爲什麼被實現?這導致我出現了第三個稍微不相關的問題:如果IDisposable被明確實現,Coverity(代碼分析)是否仍然認爲我應該處置它?

代碼示例:

var myList = new List<int>{ 1, 2, 3, 4 }; 

var evenNumbers = myList.Where(x => x % 2 == 0); 

foreach(var number in evenNumbers) 
{ 
    Console.WriteLine(number); 
} 

if(evenNumbers is IDisposable) 
{ 
    ((IDisposable)evenNumbers).Dispose(); // This line will be executed 
} 
+12

foreach循環自動爲您調用Dispose;如果代碼分析工具不知道這個事實,那麼你應該使用更準確的代碼分析工具。您可能會考慮將其作爲工具維護人員的錯誤報告。 –

+0

這完全是我的想法,但我並不是固執己見,我想我應該問社區。 –

+1

或者,您應該等待生產該分析工具的人員聘請Eric Lippert重寫他們的內容。 Coverity似乎不再存在這個問題。 –

回答

12

不,你不需要自己處置。請注意,您可以演示這種事情,而不需要任何LINQ。在這種情況下,我相信WhereListIterator<T>實際上是手寫的類,但迭代器塊顯示類似的東西:

using System; 
using System.Collections.Generic; 

public class Program 
{ 
    static void Main(string[] args) 
    { 
     var empty = Empty(); 
     Console.WriteLine(empty is IDisposable); // Prints True 
    } 

    static IEnumerable<string> Empty() 
    { 
     yield break; 
    } 
} 

這真的實現IDisposable因爲它實現不只是IEnumerable<T>IEnumerator<T>作爲優化 - 可迭代作爲也就是迭代器,通常情況下你只迭代一次。一個foreach循環將隱含地處置一個IEnumerator<T>,並且您不需要需要來處置它,除非您重複。

基本上,你很好 - 雖然可惜Coverity正在警告你。 (我自己並沒有使用Coverity,說實話 - 我不知道你是否可以在這裏調整它的行爲。)

5

如果你沒有使用foreach循環,並使用舊的方式來迭代

var v = new List<int>() { 1,2,3}; 
var enumerator = v.GetEnumerator(); 
while (enumerator.MoveNext()) 
{ 

    Console.WriteLine(enumerator.Current); 
} 

,那麼你應該調用Dispose方法