我喜欢绳子。IsNullOrEmpty方法。我想有一些东西,将允许相同的功能IEnumerable。有这样的东西吗?也许是一些收集助手类?我问的原因是,在if语句中,如果模式是(mylist != null && mylist. any()),代码看起来很混乱。使用Foo.IsAny(myList)会干净得多。
这篇文章没有给出答案:IEnumerable是空的?
我喜欢绳子。IsNullOrEmpty方法。我想有一些东西,将允许相同的功能IEnumerable。有这样的东西吗?也许是一些收集助手类?我问的原因是,在if语句中,如果模式是(mylist != null && mylist. any()),代码看起来很混乱。使用Foo.IsAny(myList)会干净得多。
这篇文章没有给出答案:IEnumerable是空的?
当前回答
另一个最佳解决方案如下检查是否为空?
for(var item in listEnumerable)
{
var count=item.Length;
if(count>0)
{
// not empty or null
}
else
{
// empty
}
}
其他回答
Jon Skeet的回答(https://stackoverflow.com/a/28904021/8207463)有一个很好的方法,使用扩展方法- Any()为NULL和EMPTY。但是他正在验证问题的所有者,以防NOT NULL。 因此,请仔细更改Jon验证AS NULL的方法为:
If (yourList?.Any() != true)
{
..your code...
}
不使用(将不验证为NULL):
If (yourList?.Any() == false)
{
..your code...
}
你也可以在验证AS NOT NULL的情况下(没有测试,只是作为例子,但没有编译器错误)做一些类似使用predicate的事情:
If (yourList?.Any(p => p.anyItem == null) == true)
{
..your code...
}
https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,8788153112b7ffd0
你可以使用哪个.NET版本,请检查:
https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.any?view=netframework-4.8#moniker-applies-to
我的做法是,利用一些现代c#特性:
选择1)
public static class Utils {
public static bool IsNullOrEmpty<T>(this IEnumerable<T> list) {
return !(list?.Any() ?? false);
}
}
选择2)
public static class Utils {
public static bool IsNullOrEmpty<T>(this IEnumerable<T> list) {
return !(list?.Any()).GetValueOrDefault();
}
}
顺便说一下,永远不要使用Count == 0或Count() == 0来检查一个集合是否为空。总是使用Linq的.Any()
下面是Marc Gravell回答的代码,以及使用它的示例。
using System;
using System.Collections.Generic;
using System.Linq;
public static class Utils
{
public static bool IsAny<T>(this IEnumerable<T> data)
{
return data != null && data.Any();
}
}
class Program
{
static void Main(string[] args)
{
IEnumerable<string> items;
//items = null;
//items = new String[0];
items = new String[] { "foo", "bar", "baz" };
/*** Example Starts Here ***/
if (items.IsAny())
{
foreach (var item in items)
{
Console.WriteLine(item);
}
}
else
{
Console.WriteLine("No items.");
}
}
}
正如他所说,并不是所有序列都是可重复的,因此代码有时可能会引起问题,因为IsAny()开始遍历序列。我怀疑Robert Harvey的回答的意思是,您通常不需要检查null和empty。通常,您可以只检查null,然后使用foreach。
为了避免两次启动序列并利用foreach,我只写了一些像这样的代码:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main(string[] args)
{
IEnumerable<string> items;
//items = null;
//items = new String[0];
items = new String[] { "foo", "bar", "baz" };
/*** Example Starts Here ***/
bool isEmpty = true;
if (items != null)
{
foreach (var item in items)
{
isEmpty = false;
Console.WriteLine(item);
}
}
if (isEmpty)
{
Console.WriteLine("No items.");
}
}
}
我猜扩展方法为您节省了几行输入,但这段代码对我来说似乎更清楚。我怀疑一些开发人员不会立即意识到IsAny(项目)实际上将开始在序列中进行步进。(当然,如果你使用了很多序列,你很快就会学会思考通过它们的步骤。)
public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source)
{
return source != null && source.Any();
}
我自己的扩展方法来检查非空和任何
由于一些资源在一次读取后会耗尽,我想为什么不将检查和读取结合起来,而不是传统的单独检查,然后读取。
首先,我们有一个更简单的检查为空的内联扩展:
public static System.Collections.Generic.IEnumerable<T> ThrowOnNull<T>(this System.Collections.Generic.IEnumerable<T> source, string paramName = null) => source ?? throw new System.ArgumentNullException(paramName ?? nameof(source));
var first = source.ThrowOnNull().First();
然后我们有一些更复杂的(好吧,至少我写它的方式)检查为空和空的内联扩展:
public static System.Collections.Generic.IEnumerable<T> ThrowOnNullOrEmpty<T>(this System.Collections.Generic.IEnumerable<T> source, string paramName = null)
{
using (var e = source.ThrowOnNull(paramName).GetEnumerator())
{
if (!e.MoveNext())
{
throw new System.ArgumentException(@"The sequence is empty.", paramName ?? nameof(source));
}
do
{
yield return e.Current;
}
while (e.MoveNext());
}
}
var first = source.ThrowOnNullOrEmpty().First();
当然,您仍然可以在不继续调用链的情况下调用两者。此外,我还包含了paramName,以便调用者可以为错误包含一个替代名称,如果它不是“源”被检查,例如。“nameof(目标)”。