Multiple enumeration and use of Any()

我是研究僧i 提交于 2021-01-27 07:27:16

问题


I'm trying to figure out what would be the proper convention for LINQ when I need to do something like the following

  • If there items, print them line-by-line
  • If there are no items, print "No items"

The way I would think to do it is like

if (items.Any())
{
    foreach (string item in items)
    {
        Console.WriteLine(item);
    }
}
else
{
    Console.WriteLine("No items");
}

However, that would technically violate the principle of multiple enumeration. A way to not violate that would be

bool any = false;
foreach (string item in items)
{
    any = true;
    Console.WriteLine(item);
}   
if (!any)
{
    Console.WriteLine("No items");
}

but clearly, that is less elegant.


回答1:


Since we are talking LINQ, how about a very LINQ solution?

foreach (var item in items.DefaultIfEmpty("No items"))
    Console.WriteLine(item);



回答2:


var itemsList = items as List<Item> ?? items.ToList();

If the IEnumerable<Item> is already a list, you're already set. If not, it calls .ToList(). Either way you end up with a list. (Resharper defaults to an array. I'm showing a list in deference to some comments.)




回答3:


This may or may not be a problem, depending on your use case, because Any() will short-circuit as soon as the condition is met, meaning the entire IEnumerable doesn't need to be enumerated.

Note the comments below which point out potential pitfalls such as the implementation being forward only or expensive.

Here's the reference source:

public static bool Any<TSource>(this IEnumerable<TSource> source) {
    if (source == null) throw Error.ArgumentNull("source");
    using (IEnumerator<TSource> e = source.GetEnumerator()) {
        if (e.MoveNext()) return true;
    }
    return false;
}


来源:https://stackoverflow.com/questions/48932548/multiple-enumeration-and-use-of-any

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