开发者

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

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

开发者_如何学Pythonvoid 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


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.


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

how about that?


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


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜