2010-02-04 16 views
5

Poniżej znajduje się kod testowy linqpad. Gdy uruchamia to błędy, ponieważ druga instancja "elementu" ma zerową listę podelementów w przeciwieństwie do pustej listy.Jak traktować puste listy, takie jak puste listy w linq?

Chciałbym traktować obie sytuacje (pusty lub pusty list) w dokładnie taki sam sposób, ale zastanawiałem się, czy był lepszy sposób niż tylko umieszczenie zerowej kontroli na liście i zainicjowanie pustej listy, gdy jest pusta.

innymi słowy, mogę to zrobić:

from si in (i.subitems == null ? new List<item>() : i.subitems) 

ale to trochę brzydki i zastanawiałem się jak mogę poprawić na to?

public class item 
{ 
    public string itemname { get; set; } 
    public List<item> subitems { get; set; } 
} 

void Main() 
{ 
    List<item> myItemList = new List<item>() 
    { 
     new item 
     { 
      itemname = "item1", 
      subitems = new List<item>() 
      { 
       new item { itemname = "subitem1" }, 
       new item { itemname = "subitem2" } 
      } 
     }, 
     new item 
     { 
      itemname = "item2" 
     } 
    }; 

    myItemList.Dump(); 

    var res = (from i in myItemList 
      from si in i.subitems 
      select new {i.itemname, subitemname = si.itemname}).ToList(); 

    res.Dump(); 
} 

jako pytanie dodatkowe, czy to samo zapytanie linq może być przedstawione jako lambda i traktować wartości zerowe w ten sam sposób?

Cheers Chris

Odpowiedz

13

Można użyć null coalescing operator

var res = (from i in myItemList 
      from si in i.subitems ?? new List<item>() 
      select new { i.itemname, subitemname = si.itemname }).ToList(); 

Ale myślę, że należy po prostu filtrować pustych się

var res = (from i in myItemList 
      where i.subitems != null 
      from si in i.subitems 
      select new { i.itemname, subitemname = si.itemname }).ToList(); 

Jeśli chodzi o wersję lambda, można powiedzieć:

var res = myItemList.Where(x => x.subitems != null) 
        .SelectMany(
         x => x.subitems.Select(
          y => new { x.itemname, subitemname = y.itemname } 
         ) 
        ); 

Ale wersja składni zapytań jest o wiele bardziej czytelna.

+0

w rzeczywistości ta druga opcja jest bardzo czytelna i nie oznacza, że ​​nowa lista musi zostać stworzona tylko po to, aby ją zignorować. dzięki –

+0

@ Chris Simpson: Dodałem wersję lambda, ponieważ poprosiłeś o nią.Wersja składni zapytań jest o wiele bardziej czytelna. – jason

+1

Naprawdę uważam, że klauzula where jest najczystszym rozwiązaniem, dlatego zaznaczam to jako odpowiedź. Ciekawi mnie tylko odpowiednik lambda, ale zgadzam się, to nie jest tak czytelne. Dzięki. –

11
from si in (i.subitems ?? new List<item>()) 

jak o tym?

+1

tak, to lepiej niż ja (a ja kopać siebie, ze nie robi, że w pierwszej kolejności), ale to nadal oznacza tworzenie obiekt po prostu go wyeliminować, który czuje się źle –

+0

Punkty bonusowe za znalezienie dobrego wykorzystania? – captncraig

+0

@captncraig Do innych zastosowań ??, zobacz http://stackoverflow.com/questions/1689530/how-useful-is-cs-operator/1689544#1689544 –

8

Można dodać (EVIL) metodę rozszerzenia do pracy dla Ciebie

public static IEnumerable<T> EnsureNotEmpty<T>(this IEnumerable<T> enumerable) { 
    if (enumerable == null) { 
    return Enumerable.Empty<T>(); 
    } else { 
    return enumerable; 
    } 
} 
+0

Czy 'Enumerable.Repeat (0)' preferowane do ' Enumerable.Empty () '? – bdukes

+0

@bdukes, Enumerable.Empty jest lepszy, ponieważ jest bardziej deklaratywny dla twojego zamiaru. Z jakiegoś powodu, ale wciąż zapominam, że jest to część struktury i zamiast tego robię Powtórzenie (0). – JaredPar

+4

Metoda powinna mieć nazwę 'SprawdźNotNull (...)'. Ponieważ 'UpewnićNotEmpty (...)' brzmi tak, jakby dodać umyślny element. : -> – herzmeister

0

Dodatkowa metoda nie pozwalałaby na wyzerowanie podelementów. Można skonstruować obiekt tak, aby domyślnie był podrzędny względem pustej listy, a następnie nie zezwalał na wartość null w podsieci ustawiającym.

To oczywiście zakłada, że ​​masz dostęp do modyfikacji przedmiotu.

null operator koalescencyjny jest to, czego szukasz, jak podkreślił Hunter Daley

Powiązane problemy