Does C# have IsNullOrEmpty for List/IEnumerable?
本文关键字:IEnumerable List for have IsNullOrEmpty Does | 更新日期: 2023-09-27 18:18:21
我知道通常空列表比NULL更受欢迎。但是我将返回NULL,主要有两个原因
- 我必须明确地检查和处理空值,避免错误和攻击。
- 便于后续
??
操作获取返回值。
没有嵌入到框架中,但是它是一个非常直接的扩展方法。
看到
/// <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出于性能原因采取了额外的步骤,将类型转换为iccollection(如果可能)。这是我从未想过要做的事。
最新更新:从c# 6.0开始,空值传播运算符可以用来表示如下简洁的表达式:
if ( list?.Count > 0 ) // For List<T>
if ( array?.Length > 0 ) // For Array<T>
或者,作为IEnumerable<T>
的更简洁、更通用的替代:
if ( enumerable?.Any() ?? false )
注1:所有上面的变量实际上反映了IsNotNullOrEmpty
,与OP问题(引用)相反:
由于运算符优先级,
IsNullOrEmpty
的等价物看起来不那么吸引人:if (!(list?.Count > 0))
注2: ?? false
是必要的,因为以下原因(摘要/引用自本帖子):
如果子成员为null
,则中使用。
?.
操作符返回null
。但[…如果我们试图获得非Nullable
成员,如Any()
方法,返回bool
[…]编译器会在Nullable<>
中"wrap"返回值。例如,Object?.Any()
将给我们bool?
(也就是Nullable<bool>
),而不是bool
。[…因为它不能隐式转换为bool
,这个表达式不能在if
注释3:作为奖励,该语句也是"线程安全的"(引用自该问题的答案):
在多线程环境中,if [enumerable]可以从另一个线程访问线程(要么因为它是一个可访问的字段,要么因为它是)在暴露给另一个线程的lambda中关闭),然后值每次计算时都可能不同[,即之前null-check
)
没有什么内置的
这是一个简单的扩展方法:
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
if(enumerable == null)
return true;
return !enumerable.Any();
}
var nullOrEmpty = list == null || !list.Any();
将前面的答案组合成c# 6.0+的简单扩展方法:
public static bool IsNullOrEmpty<T>(this IEnumerable<T> me) => !me?.Any() ?? true;
正如其他人所说,框架中没有内置任何内容,但如果您正在使用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;
}
...
如果您需要能够在非空的情况下检索所有元素,那么这里的一些答案将不起作用,因为在不可rewindable 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()
等
我修改了Matthew Vines的建议,以避免" IEnumerable可能存在的多个枚举" -问题。(参见Jon Hanna的评论)
public static bool IsNullOrEmpty(this IEnumerable items)
=> items == null
|| (items as ICollection)?.Count == 0
|| !items.GetEnumerator().MoveNext();
…单元测试:
[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 );
对我来说最好的isNullOrEmpty方法是这样的
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
return !enumerable?.Any() ?? true;
}
public static class IEnumerableExtention
{
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
if (enumerable == null)
{
return true;
}
using var enumerator = enumerable.GetEnumerator();
var isEmpty = !enumerator.MoveNext();
return isEmpty;
}
}
支持可空的一行:
public static bool IsNullOrEmpty<T>(this IEnumerable<T>? enumerable) =>
enumerable == null || !enumerable.Any();