如何检查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 == 0
或Count() == 0
来检查一个集合是否为空。 总是使用Linq的.Any()
从C#6开始,您可以使用null传播 : myList?.Any() == true
如果你仍然觉得这样太麻烦,或者更喜欢一个好的扩展方法,我会推荐Matt Greer和Marc Gravell的答案,但是为了完整性还需要一些扩展function。
他们的答案提供了相同的基本function,但从另一个angular度来看。 马特的答案使用了string.IsNullOrEmpty
forms,而马克的答案需要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; }