string.IsNullOrEmpty
方法。我希望有一个类似的方法可以用于 IEnumerable。是否有这样的方法?也许有一些集合辅助类?我之所以问这个问题是因为在 if
语句中,如果模式是 (mylist != null && mylist.Any())
,代码看起来很凌乱。如果有 Foo.IsAny(myList)
,将会更加清晰。这篇文章没有给出答案:IEnumerable is empty?。
string.IsNullOrEmpty
方法。我希望有一个类似的方法可以用于 IEnumerable。是否有这样的方法?也许有一些集合辅助类?我之所以问这个问题是因为在 if
语句中,如果模式是 (mylist != null && mylist.Any())
,代码看起来很凌乱。如果有 Foo.IsAny(myList)
,将会更加清晰。当然你可以这样写:
public static class Utils {
public static bool IsAny<T>(this IEnumerable<T> data) {
return data != null && data.Any();
}
}
不过,要小心的是,并非所有序列都是可重复的;通常情况下,我更喜欢只遍历一次,以防万一。
.Any()
是一个扩展方法,它作用于IEnumerable<T>
(或IQueryable<T>
, 不过那是另一种情况)。这个方法会消耗序列,至少部分地(尽管这意味着它已被消耗) - 它可能只需要读取一个元素(特别是如果没有谓词)。因此,由于序列(IEnumerable<T>
)不需要可重复性,这可能就是答案。没有谓词的Any()
基本上等价于 foreach(var x in sequence) { return true; } return false;
- 尽管它使用 GetEnumerator()
等而不是编译器语法。 - Marc Gravellpublic static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable) {
return enumerable == null || !enumerable.Any();
}
IEnumerable
没有 Any()
扩展方法。 - BlaiseIEnumerable<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;
}
}
if (collection?.Any() == true){
// if collection contains one or more items
}
if (collection?.Any() != true){
// if collection is null
// if collection does not contain any item
}
另一种方法是获取枚举器并调用MoveNext()方法来查看是否有任何项:
if (mylist != null && mylist.GetEnumerator().MoveNext())
{
// The list is not null or empty
}
这对于IEnumerable和IEnumerable<T>同样适用。
我采用一些现代化的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 == 0
或Count() == 0
来检查集合是否为空。始终使用Linq的.Any()
方法。
!
在某些情况下是多么难以阅读,特别是在第二个选项中;) - Fabio从C#6开始,您可以使用null传播:myList?.Any() == true
如果您仍然觉得这太冗长,或者更喜欢一个好的扩展方法,我建议使用Matt Greer和Marc Gravell的答案,但为了完整性而进行了一些扩展功能。
他们的答案提供了相同的基本功能,但每个人都从另一个角度来看。 Matt的答案使用string.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);
}
.Any()
一样做一些事情,例如:myList.AnyNotNull(item=>item.AnswerToLife == 42);
,但增加了 null 检查。myList?.Any()
返回一个 bool?
而不是 bool
,这实际上是传播 null 的效果。这可能会有所帮助
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;
}
当涉及到引用(可空)类型并且不期望在项目中出现 null 项时,可以使用此行进行验证。
myCollection?.FirstOrDefault() == null
Jon Skeet的答案(https://dev59.com/RF4b5IYBdhLWcg3wnSwd#28904021)使用扩展方法-Any()来处理NULL和EMPTY的情况,但是他在非NULL情况下验证了问题所有者。因此,请小心地将Jon的方法更改为对NULL进行验证:
If (yourList?.Any() != true)
{
..your code...
}
不要使用(将不会验证为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版本: