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

我喜欢string.IsNullOrEmpty方法。 我很想有一些东西,将允许IEnumerable相同的function。 有这样的吗? 也许有一些收集帮手类? 我问的原因是, if语句的代码看起来很混乱,如果这个模式是(mylist != null && mylist.Any()) 。 有Foo.IsAny(myList)会更干净。

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

当然你可以写:

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

但是,谨慎的是,并不是所有的序列都是可重复的; 一般来说我宁愿只走一次,以防万一。

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

下面是@Matt Greer的有用答案的一个修改版本,其中包括一个静态包装类,因此您可以将其复制粘贴到一个新的源文件中,不依赖于Linq,并添加一个通用的IEnumerable<T>重载,以避免对非通用版本的值types进行装箱。 [编辑:请注意使用IEnumerable<T>并不能防止枚举的装箱, 鸭子键入不能防止,但至less价值型集合中的元素不会每个装箱。]

 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>。

下面是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()开始顺序遍历序列。 我怀疑罗伯特·哈维的答案意味着你经常不需要检查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."); } } } 

我猜扩展方法可以节省你几行的input,但是这个代码对我来说似乎更加清晰。 我怀疑有些开发人员不会马上意识到IsAny(items)实际上会开始顺序执行。 (当然,如果你使用了很多序列,你很快就会学会思考通过它们的步骤。)

我这样做,利用一些现代的C#function:

选项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()

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

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

他们的答案提供了相同的基本function,但从另一个angular度来看。 马特的答案使用了string.IsNullOrEmptyforms,而马克的答案需要Linq的.Any()路来完成工作。

我个人倾向于使用.Any()道路,但是想从方法的其他重载中添加条件检查function:

  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的实际效果

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

分解:

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

Collection?.Any()??false如果Collection为空,则Collection?.Any()??false将会给我们,如果Collection为null ,则为null

补充一下会给我们IsEmptyOrNull

只需using System.Linq添加,并在尝试访问IEnumerable的可用方法时查看发生的IEnumerable 。 添加这个将使您能够访问名为Count()方法,就像那样简单。 只要记得调用count() :)之前检查null value

我用简单的如果检查它

看看我的解决scheme

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

我从@Matt Greer的回答中得出了这个结论

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

我想要这样的东西,同时保持Any的原始function,同时也检查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); } } 

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

这可能有帮助

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