how do I treat null lists like empty lists in linq?

回眸只為那壹抹淺笑 提交于 2019-12-10 13:08:33

问题


Below is some linqpad test code. When this runs it errors because the second instance of "item" has a null list of subitems as opposed to an empty list.

I want to treat both situations (null or empty list) in exactly the same way but I wondered if there was a cleaner way than just putting a null check on the list and initialising an empty list when there's a null.

in other words, I could do this:

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

but that's a little ugly and I wondered how I could improve on that?

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

as a bonus question, can this same linq query be represented as a lambda and treat nulls the same way?

Cheers, Chris


回答1:


You could use the 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();

But I think you should just filter the empty ones out

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

As for a lambda version you could say

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

But the query syntax version is way more readble.




回答2:


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

how about that?




回答3:


You could add an (evil) extension method to do the work for you

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



回答4:


An additional method would be not to allow subitems to be null. You could make the item constructor so that it defaults subitem to an empty list and then not allow null in the subitem setter.

That of course assumes you have access to modify item.

The null coalescing operator is what you are looking for as pointed out by Hunter Daley



来源:https://stackoverflow.com/questions/2201891/how-do-i-treat-null-lists-like-empty-lists-in-linq

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!