我喜欢绳子。IsNullOrEmpty方法。我想有一些东西,将允许相同的功能IEnumerable。有这样的东西吗?也许是一些收集助手类?我问的原因是,在if语句中,如果模式是(mylist != null && mylist. any()),代码看起来很混乱。使用Foo.IsAny(myList)会干净得多。

这篇文章没有给出答案:IEnumerable是空的?


当前回答

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

如果你仍然觉得这个方法太麻烦或者更喜欢一个好的扩展方法,我会推荐Matt Greer和Marc Gravell的答案,但为了完整性,还需要一些扩展功能。

他们的答案提供了相同的基本功能,但各从不同的角度。Matt的答案使用了字符串。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(项= >项目。AnswerToLife == 42);就像使用常规的.Any()一样,但添加了空检查

注意,使用c# 6的方式:myList?.Any()返回bool?而不是bool类型,这是传播null的实际效果

其他回答

我用简单的if来检查它

看看我的解决方案

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

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

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

下面是@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;
    }
}

下面是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 IsNotEmpty(this ICollection elements)
    {
        return elements != null && elements.Count > 0;
    }

埃杰姆:

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