2010-02-04 82 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

另一种方法是不允许子项为空。您可以创建项目构造函数,使其将子项目默认为空列表,然后在子项目设置器中不允许为空。

这当然假设您有权访问修改项目。

空合并运算符是你在找什么由亨特戴利指出