2011-12-01 12 views
6

Analiza kodu mówi mi, że Enumarble.Where(this ...) zwraca instancję WhereListIterator<T>, która jest (wygląda) typem wewnętrznym w ramach .NET, która implementuje IDisposable .Coverity, Enumerable.Where (this ...) i IDisposable

Coverity nie podoba się IDisposable, aby przejść niezaangażowany, a zatem sugeruje, że usunę wspomnianą instancję. Oczywiście nie mogę pozbyć się instancji bez sprawdzania typów, ponieważ mówi się, że zwraca Enumerable.Where(this ...), aby zwrócić IEnumerable<T>, która nie jest ihnerit z IDisposable.

Moje pytanie brzmi następująco: .NET oczekuje, że wyrzucę WhereListIterator<T>, czy też iterator się wyrzuci (powiedzmy po każdym wyliczeniu). Jeśli nie mam zamiaru się go pozbyć, to dlaczego interfejs jest zaimplementowany? Prowadzi mnie to do trzeciego, nieco niezwiązanego z sobą pytania: czy implementacja IDisposable została jawnie zaimplementowana, czy Coverity (analiza kodu) nadal uważa, że ​​powinienem ją usunąć?

Kod Przykład:

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

pętla foreach automatycznie wywołuje utylizować w jego imieniu; jeśli narzędzie do analizy kodu nie zna tego faktu, prawdopodobnie powinieneś użyć dokładniejszego narzędzia do analizy kodu. Możesz rozważyć zgłoszenie go jako błędu dla opiekunów narzędzia. –

+0

To była moja myśl, ale zamiast być upartym, pomyślałem, że powinienem zapytać społeczność. –

+1

Możesz też poczekać, aż ludzie, którzy produkują to narzędzie analityczne, zatrudnią Erica Lipperta do przepisywania swoich rzeczy. Ten problem nie występuje już w Coverity. –

Odpowiedz

12

Nie, nie trzeba, aby pozbyć się go samemu. Zauważ, że możesz pokazać takie rzeczy bez potrzeby LINQ. W tym przypadku wierzę WhereListIterator<T> jest rzeczywiście klasa odręcznie, ale blok iterator wskazuje coś podobnego:

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

To naprawdę implementuje IDisposable ponieważ realizuje nie tylko IEnumerable<T> ale również IEnumerator<T> jako optymalizacja - z iterable działa jako iterator, w tym samym przypadku, w którym wykonujesz tylko iterację raz. Pętla foreach domyślnie pozbędzie się IEnumerator<T>, a użytkownik nie będzie potrzebował , aby go pozbyć, chyba że mimo to wykonasz iterację.

W zasadzie wszystko jest w porządku - chociaż szkoda, że ​​Coverity ostrzega cię przed tym. (Sam nie korzystam z Coverity - szczerze mówiąc - nie wiem, czy jest coś, co możesz zrobić, aby poprawić jego zachowanie tutaj.)

5

jeśli nie używasz pętli foreach i używasz starej metody do iterowania

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

    Console.WriteLine(enumerator.Current); 
} 

wówczas należy wywołać metodę Dispose

Powiązane problemy