如何检查IEnumerable是否为null或空?

我爱string.IsNullOrEmpty法。我希望能为IEnumerable提供相同的功能。有这样的吗?也许是一些集合助手类?我问这个问题的原因是,在if语句中,如果模式是(mylist != null && mylist.Any()),则代码看起来很混乱。如果有Foo.IsAny(myList),那就干净多了。

这篇文章没有给出答案:IEnumerable为空。

297677 次浏览
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable) {
return enumerable == null || !enumerable.Any();
}

确定您写下:

public static class Utils {
public static bool IsAny<T>(this IEnumerable<T> data) {
return data != null && data.Any();
}
}

但是,请注意,并非所有序列都是可重复的;一般地,我宁愿只走一次,以防万一。

下面是马克·格拉维尔的回答中的代码,以及使用它的示例。

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()开始单步执行序列。我怀疑罗伯特·哈维的回答的意思是,您通常不需要检查null是否为空。通常,您可以只检查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(items)实际上将开始单步执行序列。(当然,如果您正在使用大量序列,您很快就会学会思考它们的步骤。)

下面是@Matt Greer的有用答案的修改版本,它包含一个静态包装类,因此您可以将其复制粘贴到一个新的源文件中,不依赖于LINQ,并添加一个泛型IEnumerable<T>重载,以避免在非泛型版本中发生的值类型装箱。[编辑:请注意,使用IEnumerable<T>不会阻止对枚举数进行装箱,鸭子打字也无法阻止此操作,但至少不会对值类型集合中的每个元素进行装箱。]

using System.Collections;
using System.Collections.Generic;


public static class IsNullOrEmptyExtension
{
public static bool IsNullOrEmpty(this IEnumerable source)
{
if (source != null)
{
foreach (object obj in source)
{
return false;
}
}
return true;
}


public static bool IsNullOrEmpty<T>(this IEnumerable<T> source)
{
if (source != null)
{
foreach (T obj in source)
{
return false;
}
}
return true;
}
}

另一种方法是获取枚举数并调用MoveNext()方法以查看是否有任何项:

if (mylist != null && mylist.GetEnumerator().MoveNext())
{
// The list is not null or empty
}

这适用于IEnumerable和IEnumerable<;t>;。

只需添加using System.Linq,当您尝试访问IEnumerable中的可用方法时,就会看到神奇的变化。添加此代码将使您可以访问名为Count()的方法,就这么简单。在致电count()之前,请记住检查null value:)

我这样做,利用一些现代的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 == 0Count() == 0来检查集合是否为空。始终使用LINQ的.Any()

我使用简单的if来检查它。

查看我的解决方案

foreach (Pet pet in v.Pets)
{
if (pet == null)
{
Console.WriteLine(" No pet");// enumerator is empty
break;
}
Console.WriteLine("  {0}", pet.Name);
}

从C#6开始,您可以使用空传播myList?.Any() == true

如果你仍然觉得这太笨拙,或者更喜欢一个好的扩展方法,我会推荐马特·格里尔(Matt Greer)和马克·格拉维尔(Marc Gravell)的答案,但有一些扩展的功能。

他们的答案提供了相同的基本功能,但每个人都从另一个角度来看。Matt的答案使用了string.IsNullOrEmpty,而Marc的答案使用了LINQ的.Any()来完成工作。

我个人倾向于使用.Any()路,但希望从该方法的其他过载中添加条件检查功能:

    public static bool AnyNotNull<T>(this IEnumerable<T> source, Func<T, bool> predicate = null)
{
if (source == null) return false;
return predicate == null
? source.Any()
: source.Any(predicate);
}

因此,您仍然可以执行以下操作: myList.AnyNotNull(item=>item.AnswerToLife == 42);,就像常规.Any()一样,但添加了空检查

请注意,使用C#6方式:myList?.Any()返回bool?,而不是bool,这是正在传播的实际效果NULL

我在@Matt Greer的回答的基础上构建了这个。

他完美地回答了行动组的问题。

我想要这样的东西,同时保持任何的原始功能,同时还检查NULL.我把这个贴出来,以防其他人需要类似的东西。

具体来说,我希望仍然能够传递一个谓词。

public static class Utilities
{
/// <summary>
/// Determines whether a sequence has a value and contains any elements.
/// </summary>
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
/// <param name="source">The <see cref="System.Collections.Generic.IEnumerable"/> to check for emptiness.</param>
/// <returns>true if the source sequence is not null and contains any elements; otherwise, false.</returns>
public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source)
{
return source?.Any() == true;
}


/// <summary>
/// Determines whether a sequence has a value and any element of a sequence satisfies a condition.
/// </summary>
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
/// <param name="source">An <see cref="System.Collections.Generic.IEnumerable"/> whose elements to apply the predicate to.</param>
/// <param name="predicate">A function to test each element for a condition.</param>
/// <returns>true if the source sequence is not null and any elements in the source sequence pass the test in the specified predicate; otherwise, false.</returns>
public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
return source?.Any(predicate) == true;
}
}

扩展方法的命名可能会更好。

这可能会有帮助

public static bool IsAny<T>(this IEnumerable<T> enumerable)
{
return enumerable?.Any() == true;
}


public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
return enumerable?.Any() != true;
}

我使用Bool IsCollectionNullOrEmpty = !(Collection?.Any()??false);。希望这能有所帮助。

细分:

如果集合为空,则Collection?.Any()将返回null,如果集合为空,则返回false

如果集合为空,则Collection?.Any()??false将为我们提供false;如果集合为null,则false

它的补码将给我们IsEmptyOrNull

我有同样的问题,我解决它像:

    public bool HasMember(IEnumerable<TEntity> Dataset)
{
return Dataset != null && Dataset.Any(c=>c!=null);
}

C=>C!=NULL将忽略所有NULL实体。

其他最佳解决方案如下:检查是否为空?

for(var item in listEnumerable)
{
var count=item.Length;
if(count>0)
{
// not empty or null
}
else
{
// empty
}
}
if (collection?.Any() == true){
// if collection contains more than one item
}
if (collection?.Any() != true){
// if collection is null
// if collection does not contain any item
}

我用这个:

    public static bool IsNotEmpty(this ICollection elements)
{
return elements != null && elements.Count > 0;
}

埃杰姆:

List<string> Things = null;
if (Things.IsNotEmpty())
{
//replaces ->  if (Things != null && Things.Count > 0)
}

既然有些资源在一次读取后就耗尽了,我想为什么不把检查和读取结合起来,而不是传统的单独检查,然后读取。

首先,我们有一个更简单的check-for-null内联扩展:

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

然后,我们有一个稍微复杂一点的(好吧,至少我是这样写的)check-for-null-and-empty内联扩展:

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,这样,如果检查的不是“ Source ”,则调用方可以包含错误的备用名称,例如“ NameOf(Target)”。

 public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source)
{
return source != null && source.Any();
}

我自己的扩展方法来检查不为空和任何

在没有自定义帮助程序的情况下,我建议使用?.Any() ?? false?.Any() == true,它们相对简洁,并且只需要指定一次序列。


当我想将缺少的集合视为空集合时,我使用以下扩展方法:

public static IEnumerable<T> OrEmpty<T>(this IEnumerable<T> sequence)
{
return sequence ?? Enumerable.Empty<T>();
}

此函数可以与所有LINQ方法和foreach组合,而不仅仅是.Any(),这就是为什么我更喜欢它而不是人们在这里建议的更专业的辅助函数。

JonSkeet的ANWSER(https://stackoverflow.com/a/28904021/8207463)有一个很好的方法,即使用扩展方法-Any()来表示NULL和EMPTY.但他正在验证问题的所有者,以防不为空。 因此,请小心地将Jon的验证为空的方法更改为:

If (yourList?.Any() != true)
{
..your code...
}

不使用(不会验证为NULL):

If (yourList?.Any() == false)
{
..your code...
}

您还可以在验证为NOT NULL(未测试,仅作为示例,但没有编译器错误)的情况下使用谓词:

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.

我用

    list.Where (r=>r.value == value).DefaultIfEmpty().First()

如果不匹配,则结果为NULL,否则返回其中一个对象

如果您想要列表,我相信离开first()或调用toList()将提供列表或null.

当它是关于引用(可空)类型时,以及当项中没有预期的空项时,可以使用此行进行验证。

myCollection?.FirstOrDefault() == null

IT NULL将返回TRUE

enter    public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{


try
{
return enumerable?.Any() != true;
}
catch (Exception)
{


return true;
}
   

}

代码在这里