如何在linq中处理空列表等空列表?

下面是一些linqpad测试代码。 当它运行时出错是因为“item”的第二个实例具有子项的空列表而不是空列表。

我想以完全相同的方式处理这两种情况(空或空列表),但我想知道是否有一种更简洁的方法,而不仅仅是在列表上进行空检查,并在存在空值时初始化空列表。

换句话说,我可以这样做:

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

但那有点难看,我想知道我怎么能改进呢?

 public class item { public string itemname { get; set; } public List subitems { get; set; } } void Main() { List myItemList = new List() { new item { itemname = "item1", subitems = new List() { 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并以相同的方式处理null吗?

干杯,克里斯

您可以使用null合并运算符

 var res = (from i in myItemList from si in i.subitems ?? new List() 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 } ) ); 

但查询语法版本更易读。

 from si in (i.subitems ?? new List()) 

那个怎么样?

您可以添加(邪恶的)扩展方法来为您完成工作

 public static IEnumerable EnsureNotEmpty(this IEnumerable enumerable) { if ( enumerable == null ) { return Enumerable.Empty(); } else { return enumerable; } } 

另一种方法是不允许子项为空。 您可以创建项构造函数,以便将子项默认为空列表,然后在子项setter中不允许null。

当然,假设您有权修改项目。

正如Hunter Daley指出的那样,空合并运算符就是您正在寻找的