2009-10-22 18 views
8

Niedawno stanąłem przed pytaniem do wywiadu związanym z LINQ.Pusta sekwencja w LINQ

Jaki jest pożytek z pustej sekwencji?. Zapytał "czy powinienem poprosić cię o skorzystanie z tego, gdzie go pasujesz?"

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

Nie odpowiedziałem. Pomoc jest mile widziana.

+2

Jak jest pusty ciąg utworzony? Jak to pasujesz? – Will

+0

+1 za dobre pytanie w mojej opinii. –

+0

@Stan Muszę Ci bardzo podziękować za wyjaśnienie moich wątpliwości. –

Odpowiedz

3

Można to wykorzystać, gdy chcesz szybko utworzyć IEnumerable<T> ten sposób nie trzeba utworzyć odwołanie do nowego List<T> i skorzystać z plastyczności hasła.

List<string[]> namesList = 
    new List<string[]> { names1, names2, names3 }; 

// Only include arrays that have four or more elements 
IEnumerable<string> allNames = 
    namesList.Aggregate(Enumerable.Empty<string>(), 
    (current, next) => next.Length > 3 ? current.Union(next) : current); 

Uwaga wykorzystanie Unii, ponieważ nie jest Lista nie można nazwać Dodaj metodę, ale można nazwać Unię na zasadzie IEnumerable

+0

Możesz uzyskać lepszą wydajność przy użyciu Concat zamiast Union, chyba że naprawdę musisz wykluczyć duplikaty. –

+2

Najszybszym sposobem na połączenie listy takich jak LINQ jest namesList.SelectMany (list => list.Length> 4? List: Enumerable.Empty ()). Distinct(). Robienie tego z Agregatem i Unią jest niezwykle nieefektywne. Aggregate i Concat są lepsze, ale wciąż są przestrzenią O (Nsquared) i O (N). SelectMany/Distinct to przestrzeń O (N) i O (1) (tylko 3 obiekty są tworzone). –

4

Jeśli masz pętlę, która łączy różne zestawy w zestawie wyników, możesz go użyć do zainicjowania zmiennej zestawu wyników i zapętlenia/kumulacji. Na przykład:

IEnumerable<string> results = Enumerable.Empty<string>(); 

for(....) 
{ 
    IEnumerable<string> subset = GetSomeSubset(...); 

    results = results.Union(subset); 
} 

Bez Empty trzeba by napisać null sprawdzić w swojej logice pętli:

IEnumerable<string> results = null; 

for(....) 
{ 
    IEnumerable<string> subset = GetSomeSubset(...); 

    if(results == null) 
    { 
     results = subset; 
    } 
    else 
    { 
     results = results.Union(subset); 
    } 
} 

To nie tylko musi być scenariusz pętli i nie muszą być Unią (może to być funkcja agregująca), ale jest to jeden z bardziej typowych przykładów.

+0

Dziękuję bardzo dobrze wybaczam doskonały przykład –

+0

Dobra odpowiedź na postawione pytanie. Czytelnicy powinni pamiętać, że powyższy komentarz dotyczący wydajności dotyczy również tego kodu. Używanie w ten sposób Unii jest O (Nsquared), ponieważ tworzy zestaw dla każdego związku i wypełnia go wszystkimi ciągami do tej pory. Cóż, myślę, że to technicznie O (NM). Chodzi o to, że jest bardzo powolny, a SelectMany/Distinct jest znacznie lepszy w tego rodzaju scenariuszu. –

Powiązane problemy