我喜欢string.IsNullOrEmpty
方法。我很想拥有可以为IEnumerable提供相同功能的东西。有吗 也许一些收集助手类?我要问的原因是,if
如果状态为,则语句中的代码看起来很混乱(mylist != null && mylist.Any())
。拥有它会更清洁Foo.IsAny(myList)
。
这篇文章没有给出答案:IEnumerable是否为空?。
我喜欢string.IsNullOrEmpty
方法。我很想拥有可以为IEnumerable提供相同功能的东西。有吗 也许一些收集助手类?我要问的原因是,if
如果状态为,则语句中的代码看起来很混乱(mylist != null && mylist.Any())
。拥有它会更清洁Foo.IsAny(myList)
。
这篇文章没有给出答案:IEnumerable是否为空?。
Answers:
当然,您可以这样写:
public static class Utils {
public static bool IsAny<T>(this IEnumerable<T> data) {
return data != null && data.Any();
}
}
但是,请注意并非所有序列都是可重复的。通常我宁愿只走一次,以防万一。
this
那里-我认为扩展方法被认为是null
丑陋设计的标志。
.Any()
是可用于IEnumerable<T>
(或IQueryable<T>
,尽管是另一种情况)的扩展方法。这样做消耗序列,至少部分地(尽管仍然意味着它被消耗) -它可能只需要读取一个元素(特别是如果没有谓词)。这样,由于序列(IEnumerable<T>
)不需要可重复,因此就可以了。Any()
没有谓词实质上等于foreach(var x in sequence) { return true; } return false;
-尽管它使用GetEnumerator()
etc而不是编译器语法
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable) {
return enumerable == null || !enumerable.Any();
}
IEnumerable
没有Any()
扩展名。
这是@Matt Greer的有用答案的修改版本,其中包括静态包装器类,因此您可以将其复制粘贴到新的源文件中,而不依赖Linq,并添加通用IEnumerable<T>
重载以避免对值类型进行装箱非通用版本会发生这种情况。[编辑:请注意,使用of 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;
}
}
另一种方法是获取Enumerator并调用MoveNext()方法以查看是否有任何项目:
if (mylist != null && mylist.GetEnumerator().MoveNext())
{
// The list is not null or empty
}
这适用于IEnumerable以及IEnumerable <T>。
IEnumerable<T>
,因为非泛型IEnumerable
未实现IDisposable
。
我的方法是利用一些现代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()
!
可能是一个很好的例子,特别是在第二种选择中;)
这可能会有所帮助
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;
}
从C#6开始,您可以使用null传播:myList?.Any() == true
如果您仍然觉得这个问题过于冗长或不喜欢使用一种很好的扩展方法,我会推荐Matt Greer和Marc Gravell的答案,但其中有些扩展功能可以确保完整性。
他们的答案提供了相同的基本功能,但每个答案都是从另一个角度出发的。马特(Matt)的答案使用string.IsNullOrEmpty
-mentality,而马克(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);
}
所以,你仍然可以做这样的事情:
myList.AnyNotNull(item=>item.AnswerToLife == 42);
你可以与常规的.Any()
,但与添加的空校验
请注意,使用C#6方式:myList?.Any()
返回a bool?
而不是a bool
,这是传播 null 的实际效果
这是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()
开始逐步执行序列。我怀疑罗伯特·哈维(Robert Harvey)的答案意味着您通常不需要检查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.");
}
}
}
我想扩展方法可以为您节省几行输入,但是这段代码对我来说似乎更清晰。我怀疑有些开发人员不会立即意识到这IsAny(items)
实际上将开始逐步执行该序列。(当然,如果您使用了很多序列,那么您很快就会学会思考如何通过这些序列。)
我用Bool IsCollectionNullOrEmpty = !(Collection?.Any()??false);
。希望这可以帮助。
分解:
Collection?.Any()
null
如果Collection为null,并且Collection为空,则将返回false
。
Collection?.Any()??false
false
如果Collection为空,并且false
Collection为,将给我们null
。
补充将给我们IsEmptyOrNull
。
乔恩·斯基特(Jon Skeet)的anwser(https://stackoverflow.com/a/28904021/8207463)使用扩展方法-Any()表示NULL和EMPTY,这是一种很好的方法。但是他正在验证问题的所有者,以防万一。因此,请谨慎地将Jon的验证AS NULL的方法更改为:
If (yourList?.Any() != true)
{
..your code...
}
不要使用(不会验证AS 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版本,请检查:
我根据@Matt Greer的答案建立了这个
他完美地回答了OP的问题。
我想要这样的东西,同时保持Any的原始功能,同时还要检查null。如果有人需要类似的东西,我会发布此信息。
具体来说,我希望仍然能够传递谓词。
public static class Utilities
{
/// <summary>
/// Determines whether a sequence has a value and contains any elements.
/// </summary>
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
/// <param name="source">The <see cref="System.Collections.Generic.IEnumerable"/> to check for emptiness.</param>
/// <returns>true if the source sequence is not null and contains any elements; otherwise, false.</returns>
public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source)
{
return source?.Any() == true;
}
/// <summary>
/// Determines whether a sequence has a value and any element of a sequence satisfies a condition.
/// </summary>
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
/// <param name="source">An <see cref="System.Collections.Generic.IEnumerable"/> whose elements to apply the predicate to.</param>
/// <param name="predicate">A function to test each element for a condition.</param>
/// <returns>true if the source sequence is not null and any elements in the source sequence pass the test in the specified predicate; otherwise, false.</returns>
public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
return source?.Any(predicate) == true;
}
}
扩展方法的命名可能会更好。
另一个最佳解决方案如下,检查是否为空?
for(var item in listEnumerable)
{
var count=item.Length;
if(count>0)
{
// not empty or null
}
else
{
// empty
}
}
listEnumerable
为null,这将不起作用,这是眼前的问题
由于一次读取后会耗尽一些资源,所以我想为什么不将检查和读取结合起来,而不是传统的单独检查然后读取。
首先,我们有一个简单的检查空内联扩展名:
public static System.Collections.Generic.IEnumerable<T> ThrowOnNull<T>(this System.Collections.Generic.IEnumerable<T> source, string paramName = null) => source ?? throw new System.ArgumentNullException(paramName ?? nameof(source));
var first = source.ThrowOnNull().First();
然后,我们要多花点时间(至少是我编写它的方式)来检查是否为空的内联扩展:
public static System.Collections.Generic.IEnumerable<T> ThrowOnNullOrEmpty<T>(this System.Collections.Generic.IEnumerable<T> source, string paramName = null)
{
using (var e = source.ThrowOnNull(paramName).GetEnumerator())
{
if (!e.MoveNext())
{
throw new System.ArgumentException(@"The sequence is empty.", paramName ?? nameof(source));
}
do
{
yield return e.Current;
}
while (e.MoveNext());
}
}
var first = source.ThrowOnNullOrEmpty().First();
当然,您仍然可以在不继续通话链的情况下同时拨打这两个电话。另外,我包括了paramName,这样,如果未检查“源”,则调用者可以包括错误的备用名称,例如“ nameof(target)”。
如果没有自定义帮助程序,我会推荐一个?.Any() ?? false
或?.Any() == true
一个相对简洁的方法,只需指定一次即可。
当我想将缺失的集合当作一个空集合时,我使用以下扩展方法:
public static IEnumerable<T> OrEmpty<T>(this IEnumerable<T> sequence)
{
return sequence ?? Enumerable.Empty<T>();
}
该函数可以与所有LINQ方法结合使用foreach
,而不仅仅是与LINQ方法结合使用.Any()
,这就是为什么我更喜欢它而不是人们在这里建议的更专门的帮助器函数。
看看这个开源库:Nzr.ToolBox
public static bool IsEmpty(this System.Collections.IEnumerable enumerable)
我用简单的检查一下
看看我的解决方案
foreach (Pet pet in v.Pets)
{
if (pet == null)
{
Console.WriteLine(" No pet");// enumerator is empty
break;
}
Console.WriteLine(" {0}", pet.Name);
}