2010-02-04 73 views
5

下面是一些linqpad測試代碼。當它運行錯誤時,因爲「item」的第二個實例具有與空列表相反的子列表的空列表。如何處理空列表,如linq中的空列表?

我想治療以完全相同的方式這兩種情況下(null或空單),但我想知道是否有比只是把名單上的空校驗和初始化列表爲空時,有一個空一個更清潔的方式。

換句話說,我可以這樣做:

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

,但這是一個難看一點,我不知道我怎麼能提高呢?

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

的獎金問題,可以在此相同的LINQ查詢被表示爲Lambda和處理空值以同樣的方式?

乾杯,克里斯

回答

13

您可以使用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(); 

但我認爲你應該只是篩選空的了

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

至於lambda版本,你可以說

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

但查詢語法版本更方便。

+0

實際上,第二個選項是非常可讀的,並不意味着一個新的列表需要被創建只能被忽略。謝謝 – 2010-02-04 18:16:14

+0

@Chris Simpson:自從您提出要求之後,我添加了lambda版本。查詢語法版本更可讀。 – jason 2010-02-04 18:26:16

+1

我真的認爲where子句是最乾淨的解決方案,所以我將其標記爲答案。我只是對lambda相當好奇,但我同意,它不是可讀的。謝謝。 – 2010-02-04 18:58:55

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

怎麼樣?

+1

啊,這是比我好(我踢自己沒有這樣做擺在首位),但它仍然意味着創造一個簡單的消除它的感覺很差的對象 – 2010-02-04 17:49:41

+0

尋找一個好用的獎勵點? – captncraig 2010-02-04 17:50:35

+0

@captncraig對於??的其他用途,請參閱http://stackoverflow.com/questions/1689530/how-useful-is-cs-operator/1689544#1689544 – 2010-02-04 17:56:03

8

您可以添加一個(惡)擴展方法做的工作對你

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

是'Enumerable.Repeat (0)'比' Enumerable.Empty ()'? – bdukes 2010-02-04 17:49:57

+0

@bdukes,Enumerable.Empty更好,因爲它更能說明你的意圖。出於某種原因,儘管我一直忘記它是框架的一部分,而是重複(0)。 – JaredPar 2010-02-04 17:52:08

+4

該方法應該被稱爲'EnsureNotNull(...)'。因爲'EnsureNotEmpty(...)'聽起來像會添加一個有意識的項目。 : - > – herzmeister 2010-02-04 17:58:39

0

另一種方法是不允許子項爲空。您可以創建項目構造函數,使其將子項目默認爲空列表,然後在子項目設置器中不允許爲空。

這當然假設您有權訪問修改項目。

空合併運算符是你在找什麼由亨特戴利指出