C#对于List / IEnumerable是否有IsNullOrEmpty?
我知道一般空列表比NULL更喜欢。 但是我将返回NULL,主要有两个原因
- 我必须明确地检查和处理空值,以避免错误和攻击。
- 这很容易执行
??
之后的操作来获得返回值。
对于string,我们有IsNullOrEmpty。 有没有什么从C#本身做List或IEnumerable同样的事情?
没有东西被纳入框架,但它是一个非常直接的扩展方法。
看这里
/// <summary> /// Determines whether the collection is null or contains no elements. /// </summary> /// <typeparam name="T">The IEnumerable type.</typeparam> /// <param name="enumerable">The enumerable, which may be null or empty.</param> /// <returns> /// <c>true</c> if the IEnumerable is null or empty; otherwise, <c>false</c>. /// </returns> public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable) { if (enumerable == null) { return true; } /* If this is a list, use the Count property for efficiency. * The Count property is O(1) while IEnumerable.Count() is O(N). */ var collection = enumerable as ICollection<T>; if (collection != null) { return collection.Count < 1; } return !enumerable.Any(); }
由于性能的原因,Daniel Vaughan采取了额外的步骤将其投射到ICollection(在可能的情况下)。 一些我不会想到的事情。
没有内置任何东西。
这是一个简单的扩展方法:
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable) { if(enumerable == null) return true; return !enumerable.Any(); }
后期更新 :自C#6.0以来,可以使用空传播操作符来表示简洁,如下所示:
if (enumerable?.Any() ?? false)
注1: ?? false
?? false
是必要的,因为以下原因(摘要/引自本文 ):
?.
如果子成员为null
则运算符将返回null
。 但是,如果我们尝试获取非Nullable
成员,如Any()
方法,则返回bool
[…],编译器将用Nullable<>
包装返回值。 例如,Object?.Any()
会给我们bool?
(可为Nullable<bool>
),而不是bool
。 […]因为它不能被隐式地转换成bool
这个expression式不能用在if
注2:作为奖励,声明也是“线程安全的”(引自这个问题的答案):
在multithreading上下文中,如果[ enumerable ]可以从另一个线程访问(或者是因为它是一个可访问的字段,或者是因为它在暴露给另一个线程的lambda中closures了),那么每次计算它的值就可能不同[ ieprior null – 检查 ]
var nullOrEmpty = list == null || !list.Any();
如果您需要在不为空的情况下检索所有元素,那么这里的某些答案将不起作用,因为对不可回退的enumerable调用Any()
会“忘记”一个元件。
你可以采取不同的方法,将空值转换为空值:
bool didSomething = false; foreach(var element in someEnumeration ?? Enumerable.Empty<MyType>()) { //some sensible thing to do on element... didSomething = true; } if(!didSomething) { //handle the fact that it was null or empty (without caring which). }
同样(someEnumeration ?? Enumerable.Empty<MyType>()).ToList()
等可以使用。
正如其他人所说,框架没有内置任何东西,但如果你使用的是Castle,那么Castle.Core.Internal就是这样。
using Castle.Core.Internal; namespace PhoneNumbers { public class PhoneNumberService : IPhoneNumberService { public void ConsolidateNumbers(Account accountRequest) { if (accountRequest.Addresses.IsNullOrEmpty()) // Addresses is List<T> { return; } ...
我修改了Matthew Vines的build议,以避免“IEnumerable的可能的多个枚举” – 问题。 (另见Jon Hanna的评论)
public static bool IsNullOrEmpty(this IEnumerable items) => items == null || (items as ICollection)?.Count == 0 || !items.GetEnumerator().MoveNext();
…和unit testing:
[Test] public void TestEnumerableEx() { List<int> list = null; Assert.IsTrue(list.IsNullOrEmpty()); list = new List<int>(); Assert.IsTrue(list.IsNullOrEmpty()); list.AddRange(new []{1, 2, 3}); Assert.IsFalse(list.IsNullOrEmpty()); var enumerator = list.GetEnumerator(); for(var i = 1; i <= list.Count; i++) { Assert.IsFalse(list.IsNullOrEmpty()); Assert.IsTrue(enumerator.MoveNext()); Assert.AreEqual(i, enumerator.Current); } Assert.IsFalse(list.IsNullOrEmpty()); Assert.IsFalse(enumerator.MoveNext()); }
var nullOrEmpty = !( list?.Count > 0 );
把以前的答案放到C#6.0+的简单扩展方法中:
public static bool IsNullOrEmpty<T>(this IEnumerable<T> me) => !me?.Any() ?? true;