问题
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