简体   繁体   English

如何检查 IEnumerable 是 null 还是空的?

[英]How to check if IEnumerable is null or empty?

I love string.IsNullOrEmpty method.我喜欢string.IsNullOrEmpty方法。 I'd love to have something that would allow the same functionality for IEnumerable.我很想拥有可以为 IEnumerable 提供相同功能的东西。 Is there such?有这样的吗? Maybe some collection helper class?也许一些收集助手 class? The reason I am asking is that in if statements the code looks cluttered if the patter is (mylist.= null && mylist.Any()) .我问的原因是,在if语句中,如果模式是(mylist.= null && mylist.Any()) ,代码看起来很混乱。 It would be much cleaner to have Foo.IsAny(myList) .拥有Foo.IsAny(myList)会干净得多。

This post doesn't give that answer: IEnumerable is empty?这篇文章没有给出答案: IEnumerable is empty? . .

Sure you could write that:当然你可以这样写:

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

however, be cautious that not all sequences are repeatable;但是,请注意并非所有序列都是可重复的; generally I prefer to only walk them once, just in case.通常我更喜欢只走一次,以防万一。

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

Here's a modified version of @Matt Greer's useful answer that includes a static wrapper class so you can just copy-paste this into a new source file, doesn't depend on Linq, and adds a generic IEnumerable<T> overload, to avoid the boxing of value types that would occur with the non-generic version.这是@Matt Greer 有用答案的修改版本,其中包含一个静态包装器类,因此您只需将其复制粘贴到新的源文件中,不依赖于 Linq,并添加通用IEnumerable<T>重载,以避免非泛型版本会发生的值类型的装箱。 [EDIT: Note that use of IEnumerable<T> does not prevent boxing of the enumerator, duck-typing can't prevent that, but at least the elements in a value-typed collection will not each be boxed.] [编辑:请注意,使用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;
    }
}

Another way would be to get the Enumerator and call the MoveNext() method to see if there are any items:另一种方法是获取 Enumerator 并调用 MoveNext() 方法以查看是否有任何项目:

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

This works for IEnumerable as well as IEnumerable<T>.这适用于 IEnumerable 以及 IEnumerable<T>。

The way I do it, taking advantage of some modern C# features:我这样做的方式,利用了一些现代 C# 功能:

Option 1)选项1)

public static class Utils {
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> list) {
        return !(list?.Any() ?? false);
    }
}

Option 2)选项 2)

public static class Utils {
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> list) {
        return !(list?.Any()).GetValueOrDefault();
    }
}

And by the way, never use Count == 0 or Count() == 0 just to check if a collection is empty.顺便说一句,永远不要使用Count == 0Count() == 0来检查集合是否为空。 Always use Linq's .Any()始终使用 Linq 的.Any()

Starting with C#6 you can use null propagation : myList?.Any() == true从 C#6 开始,您可以使用空传播myList?.Any() == true

If you still find this too cloggy or prefer a good ol' extension method, I would recommend Matt Greer and Marc Gravell's answers, yet with a bit of extended functionality for completeness.如果您仍然觉得这太麻烦或者更喜欢一个好的 ol' 扩展方法,我会推荐 Matt Greer 和 Marc Gravell 的答案,但为了完整性,还有一些扩展功能。

Their answers provide the same basic functionality, but each from another perspective.他们的答案提供了相同的基本功能,但每个都从不同的角度。 Matt's answer uses the string.IsNullOrEmpty -mentality, whereas Marc's answer takes Linq's .Any() road to get the job done. Matt 的回答使用string.IsNullOrEmpty -mentality,而 Marc 的回答采用 Linq 的.Any()来完成工作。

I am personally inclined to use the .Any() road, but would like to add the condition checking functionality from the method's other overload :我个人倾向于使用.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);
    }

So you can still do things like : myList.AnyNotNull(item=>item.AnswerToLife == 42);所以你仍然可以做这样的事情: myList.AnyNotNull(item=>item.AnswerToLife == 42); as you could with the regular .Any() but with the added null check就像使用常规.Any()但添加了空检查

Note that with the C#6 way: myList?.Any() returns a bool?请注意,使用 C#6 方式: myList?.Any()返回一个bool? rather than a bool , which is the actual effect of propagating null而不是bool ,这是传播null 的实际效果

This may help这可能有帮助

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

Here's the code from Marc Gravell's answer , along with an example of using it.这是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.");
        }
    }
}

As he says, not all sequences are repeatable, so that code may sometimes cause problems, because IsAny() starts stepping through the sequence.正如他所说,并非所有序列都是可重复的,因此代码有时可能会导致问题,因为IsAny()开始逐步执​​行序列。 I suspect what Robert Harvey's answer meant was that you often don't need to check for null and empty.我怀疑Robert Harvey 的回答意味着您通常不需要检查nullempty。 Often, you can just check for null and then use foreach .通常,您可以只检查 null 然后使用foreach

To avoid starting the sequence twice and take advantage of foreach , I just wrote some code like this:为了避免两次启动序列并利用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.");
        }
    }
}

I guess the extension method saves you a couple of lines of typing, but this code seems clearer to me.我猜扩展方法为您节省了几行输入,但这段代码对我来说似乎更清晰。 I suspect that some developers wouldn't immediately realize that IsAny(items) will actually start stepping through the sequence.我怀疑有些开发人员不会立即意识到IsAny(items)实际上会开始逐步执​​行序列。 (Of course if you're using a lot of sequences, you quickly learn to think about what steps through them.) (当然,如果你使用了很多序列,你很快就会学会思考通过它们的步骤。)

I use Bool IsCollectionNullOrEmpty = !(Collection?.Any()??false);我使用Bool IsCollectionNullOrEmpty = !(Collection?.Any()??false); . . Hope this helps.希望这可以帮助。

Breakdown:分解:

Collection?.Any() will return null if Collection is null, and false if Collection is empty. Collection?.Any()将在 Collection 为 null 时返回null如果 Collection 为空则返回false

Collection?.Any()??false will give us false if Collection is empty, and false if Collection is null . Collection?.Any()??false会给我们false ,如果集合是空的, false ,如果集合是null

Complement of that will give us IsEmptyOrNull . IsEmptyOrNull补充将给我们IsEmptyOrNull

Jon Skeet's anwser ( https://stackoverflow.com/a/28904021/8207463 ) has a good approach using Extension Method - Any() for NULL and EMPTY. Jon Skeet 的 anwser ( https://stackoverflow.com/a/28904021/8207463 ) 有一个使用扩展方法的好方法 - Any() 用于 NULL 和 EMPTY。 BUT he´s validating the questions´owner in case for NOT NULL.但他正在验证问题的所有者,以防为 NOT NULL。 So carefully change Jon´s approach to validate AS NULL to:所以小心地将 Jon 验证 AS NULL 的方法更改为:

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

DO NOT use ( will not validate AS NULL):不要使用(不会验证为 NULL):

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

You can also in case validating AS NOT NULL ( NOT tested just as example but without compiler error) do something like using predicate :您还可以在验证 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 https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,8788153112b7ffd0

For which .NET version you can use it please check:您可以使用哪个 .NET 版本,请检查:

https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.any?view=netframework-4.8#moniker-applies-to https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.any?view=netframework-4.8#moniker-applies-to

I built this off of the answer by @Matt Greer根据@Matt Greer答案构建了这个

He answered the OP's question perfectly.他完美地回答了OP的问题。

I wanted something like this while maintaining the original capabilities of Any while also checking for null.我想要这样的东西,同时保持 Any 的原始功能,同时还要检查 null。 I'm posting this in case anyone else needs something similar.我发布这个以防其他人需要类似的东西。

Specifically I wanted to still be able to pass in a predicate.具体来说,我希望仍然能够传入谓词。

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

The naming of the extension method could probably be better.扩展方法的命名可能会更好。

I had the same problem and I solve it like :我遇到了同样的问题,我解决了它:

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

"c=>c!=null" will ignore all the null entities. "c=>c!=null" 将忽略所有空实体。

可以使用这一行进行验证

myCollection?.FirstOrDefault() == null

I used simple if to check for it我使用简单的 if 来检查它

check out my solution查看我的解决方案

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

The other best solution as below to check empty or not ?另一个最佳解决方案如下检查是否为空?

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

I use this one:我用这个:

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

Since some resources are exhausted after one read, I thought why not combine the checks and the reads, instead of the traditional separate check, then read.既然有些资源一读就用完了,我想为什么不把检查和阅读结合起来,而不是传统的单独检查,然后阅读。

First we have one for the simpler check-for-null inline extension:首先,我们有一个用于更简单的 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();

Then we have the little more involved (well, at least the way I wrote it) check-for-null-and-empty inline extension:然后我们有更多的参与(好吧,至少是我写的方式)检查空和空的内联扩展:

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

You can of course still call both without continuing the call chain.当然,您仍然可以在不继续调用链的情况下调用两者。 Also, I included the paramName, so that the caller may include an alternate name for the error if it's not "source" being checked, eg "nameof(target)".此外,我还包括了 paramName,以便调用者可以在未检查“源”的情况下包含错误的备用名称,例如“nameof(target)”。

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

my own extension method to check Not null and Any我自己的扩展方法来检查 Not null 和 Any

Without custom helpers I recommend either ?.Any() ?? false如果没有自定义助手,我推荐?.Any() ?? false ?.Any() ?? false or ?.Any() == true which are relatively concise and only need to specify the sequence once. ?.Any() ?? false?.Any() == true相对简洁,只需要指定一次序列。


When I want to treat a missing collection like an empty one, I use the following extension method:当我想将丢失的集合视为空集合时,我使用以下扩展方法:

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

This function can be combined with all LINQ methods and foreach , not just .Any() , which is why I prefer it over the more specialized helper functions people are proposing here.这个函数可以与所有 LINQ 方法和foreach ,而不仅仅是.Any() ,这就是为什么我更喜欢它而不是人们在这里提出的更专业的帮助函数。

I use我用

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

The result will be null if no match, otherwise returns one of the objects如果不匹配,结果将为 null,否则返回对象之一

If you wanted the list, I believe leaving of First() or calling ToList() will provide the list or null.如果您想要列表,我相信离开 First() 或调用 ToList() 将提供列表或 null。

it null will return true它 null 将返回 true

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

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

            return true;
        }
   
    }

code here代码在这里

just add using System.Linq and see the magic happening when you try to access the available methods in the IEnumerable .只需添加using System.Linq并查看当您尝试访问IEnumerable的可用方法时发生的神奇。 Adding this will give you access to method named Count() as simple as that.添加它将使您能够访问名为Count()方法,就这么简单。 just remember to check for null value before calling count() :)只记得在调用count()之前检查null value :)

看看这个开源库: Nzr.ToolBox

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM