如何检查IEnumerable是空还是空?

时间:2011-02-18 22:44:21

标签: c# .net linq collections ienumerable

我喜欢string.IsNullOrEmpty方法。我很想拥有能够为IEnumerable提供相同功能的东西。有这样的吗?也许一些收集助手班?我问的原因是,在if语句中,如果模式为(mylist != null && mylist.Any()),则代码看起来很混乱。拥有Foo.IsAny(myList)会更加清晰。

这篇文章没有给出答案:IEnumerable is empty?

22 个答案:

答案 0 :(得分:166)

当然可以写出:

public static class Utils {
    public static bool IsAny<T>(this IEnumerable<T> data) {
        return data != null && data.Any();
    }
}
但是,要小心并非所有序列都是可重复的; 一般我更喜欢只走一次,以防万一。

答案 1 :(得分:114)

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

答案 2 :(得分:20)

这里是@Matt Greer的有用答案的修改版本,其中包含一个静态包装类,因此您可以将其复制粘贴到新的源文件中,不依赖于Linq,以及添加通用IEnumerable<T>重载,以避免非泛型版本会出现的值类型的装箱。 [编辑:请注意,使用IEnumerable<T>不会阻止对枚举器进行装箱,duck-typing无法阻止,但至少值类型集合中的元素不会被装箱。 ]

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

答案 3 :(得分:13)

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

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

这适用于IEnumerable以及IEnumerable&lt; T&gt;。

答案 4 :(得分:6)

我这样做,利用一些现代的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()

答案 5 :(得分:5)

这可能会有所帮助

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

答案 6 :(得分:3)

从C#6开始,您可以使用null propagationmyList?.Any() == true

如果你仍然觉得这太过于无聊或者更喜欢一个好的扩展方法,我会推荐Matt Greer和Marc Gravell的答案,但还有一些扩展功能可以完整。

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

我个人倾向于使用.Any()道路,但想要从方法的other overload中添加条件检查功能:

    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

答案 7 :(得分:2)

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

故障:

如果Collection为null,

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

如果Collection为空,则

Collection?.Any()??false会向我们false;如果Collection为false,则null会为我们提供。{/ p>

对此的补充将给我们IsEmptyOrNull

答案 8 :(得分:2)

Jon Skeet的anwser(https://stackoverflow.com/a/28904021/8207463)使用扩展方法-NULL和EMPTY的Any()具有很好的方法。但是他正在验证问题的所有者,以防万一。 因此,请谨慎地将Jon的验证AS NULL的方法更改为:

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

请勿使用(不会验证AS NULL):

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

您还可以在验证AS 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://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.any?view=netframework-4.8#moniker-applies-to

答案 9 :(得分:2)

以下是Marc Gravell's answer的代码,以及使用它的示例。

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's answer的含义是您通常不需要检查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)实际上会开始逐步完成序列。 (当然,如果你使用了很多序列,你很快就会学会考虑通过它们的步骤。)

答案 10 :(得分:1)

我是在answer by @Matt Greer

之上建立起来的

他完美地回答了OP的问题。

在保持Any的原始功能同时还检查null时,我想要这样的东西。我发布这个以防其他人需要类似的东西。

具体来说,我仍希望能够传入谓词。

public static class Utilities
{
    // Will return true if it is not null and contains elements.
    public static bool NotNullAny<T>(this IEnumerable<T> enumerable)
    {
        return enumerable != null && enumerable.Any();
    }

    // Will return true if it is not null and contains elements that satisfy the condition.
    public static bool NotNullAny<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)
    {
        return enumerable != null && enumerable.Any(predicate);
    }
}

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

答案 11 :(得分:0)

我用简单的if来检查它

查看我的解决方案

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

答案 12 :(得分:0)

只需添加using System.Linq,当您尝试访问IEnumerable中的可用方法时,就会发现神奇的事情。添加此项将使您可以访问名为Count()的方法。只需记住在致电null value之前检查count():)

答案 13 :(得分:0)

以下另一个最佳解决方案是否检查空?

for(var item in listEnumerable)
{
 var count=item.Length;
  if(count>0)
  {
         // not empty or null
   }
  else
  {
       // empty
  }
}

答案 14 :(得分:0)

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
}

答案 15 :(得分:0)

我用这个:

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

Ejem:

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

答案 16 :(得分:0)

由于一次读取后一些资源已耗尽,我想为什么不将检查和读取结合起来,而不是传统的单独检查然后读取。

首先,我们有一个简单的检查空内联扩展名:

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,这样,如果未检查错误的“源”,则调用者可以包括该错误的备用名称。 “名称(目标)”。

答案 17 :(得分:0)

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

我自己的扩展方法来检查Not null and Any

答案 18 :(得分:0)

在没有自定义帮助程序的情况下,我推荐?.Any() ?? false?.Any() == true,它们比较简洁,只需要指定一次顺序即可。


当我想将缺失的集合当作一个空集合时,我使用以下扩展方法:

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

此功能可以与所有LINQ方法和foreach结合使用,而不仅仅是.Any(),这就是为什么我更喜欢它而不是人们在这里建议的更专业的帮助器功能。

答案 19 :(得分:0)

我用

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

如果不匹配,结果将为null,否则返回对象之一

如果您想要该列表,我相信离开First()或调用ToList()将提供该列表或为空。

答案 20 :(得分:0)

可以使用此行进行验证

myCollection?.FirstOrDefault() == null

答案 21 :(得分:-1)

看看这个开源库:Nzr.ToolBox

public static bool IsEmpty(this System.Collections.IEnumerable enumerable)