我喜欢 string.IsNullOrEmpty
方法。我很想拥有一些允许 IEnumerable 具有相同功能的东西。有这样的吗?也许一些收集助手类?我问的原因是在 if
语句中,如果模式是 (mylist != null && mylist.Any())
,代码看起来很混乱。有 Foo.IsAny(myList)
会干净得多。
这篇文章没有给出这个答案:IEnumerable is empty?。
当然你可以这样写:
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();
}
IEnumerable
没有 Any()
扩展名。
这是@Matt Greer 的有用答案的修改版本,其中包括一个静态包装类,因此您可以将其复制粘贴到一个新的源文件中,不依赖于 Linq,并添加了一个通用的 IEnumerable<T>
重载,以避免装箱非泛型版本会出现的值类型。 [编辑:请注意,使用 IEnumerable<T>
不会阻止枚举数的装箱,duck-typing 不能阻止,但至少值类型集合中的元素不会被装箱。]
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
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()
!
的好例子,特别是在第二个选项中;)
if (collection?.Any() == true){
// if collection contains more than one item
}
if (collection?.Any() != true){
// if collection is null
// if collection does not contain any item
}
从 C#6 开始,您可以使用 null propagation:myList?.Any() == true
如果您仍然觉得这太麻烦或者更喜欢一个好的 ol' 扩展方法,我会推荐 Matt Greer 和 Marc Gravell 的答案,但为了完整性,需要一些扩展功能。
他们的答案提供了相同的基本功能,但每个都从另一个角度。 Matt 的答案使用了 string.IsNullOrEmpty
心态,而 Marc 的答案则采用了 Linq 的 .Any()
方法来完成工作。
我个人倾向于使用 .Any()
路,但想从方法的 other overload 添加条件检查功能:
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 检查
请注意,使用 C#6 方式:myList?.Any()
返回一个 bool?
而不是 bool
,这是 propagating 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;
}
Jon Skeet 的 anwser (https://stackoverflow.com/a/28904021/8207463) 有一个使用扩展方法的好方法 - Any() 用于 NULL 和 EMPTY。但他正在验证问题的所有者,以防不为空。因此,请小心地将 Jon 验证 AS 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 版本,请检查:
这是来自 Marc Gravell's answer 的代码,以及使用它的示例。
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's answer 的意思是您通常不需要检查 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 为空,Collection?.Any()
将返回 null
,如果 Collection 为空,则返回 false
。
如果 Collection 为空,Collection?.Any()??false
将为我们提供 false
,如果 Collection 为 null
,则为 false
。
对此的补充将给我们IsEmptyOrNull
。
当它是关于引用(可为空)类型以及项目中预期没有空项目时,可以使用这一行进行验证
myCollection?.FirstOrDefault() == null
我有同样的问题,我像这样解决它:
public bool HasMember(IEnumerable<TEntity> Dataset)
{
return Dataset != null && Dataset.Any(c=>c!=null);
}
"c=>c!=null" 将忽略所有空实体。
我在 answer by @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;
}
}
扩展方法的命名可能会更好。
我用简单的 if 来检查它
查看我的解决方案
foreach (Pet pet in v.Pets)
{
if (pet == null)
{
Console.WriteLine(" No pet");// enumerator is empty
break;
}
Console.WriteLine(" {0}", pet.Name);
}
下面的另一个最佳解决方案是检查是否为空?
for(var item in listEnumerable)
{
var count=item.Length;
if(count>0)
{
// not empty or null
}
else
{
// empty
}
}
listEnumerable
为空,这将不起作用,这是手头的问题
我用这个:
public static bool IsNotEmpty(this ICollection elements)
{
return elements != null && elements.Count > 0;
}
埃杰姆:
List<string> Things = null;
if (Things.IsNotEmpty())
{
//replaces -> if (Things != null && Things.Count > 0)
}
由于一些资源在一次读取后耗尽,我想为什么不将检查和读取结合起来,而不是传统的单独检查,然后读取。
首先,我们有一个更简单的 check-for-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();
然后我们有更多的参与(嗯,至少我写它的方式)check-for-null-and-empty inline extension:
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)”。
public static bool AnyNotNull<TSource>(this IEnumerable<TSource> source)
{
return source != null && source.Any();
}
我自己的扩展方法来检查 Not null 和 Any
如果没有自定义助手,我推荐使用 ?.Any() ?? false
或 ?.Any() == true
,它们相对简洁,只需要指定一次序列。
当我想将丢失的集合视为空集合时,我使用以下扩展方法:
public static IEnumerable<T> OrEmpty<T>(this IEnumerable<T> sequence)
{
return sequence ?? Enumerable.Empty<T>();
}
此函数可以与所有 LINQ 方法和 foreach
组合,而不仅仅是 .Any()
,这就是为什么我更喜欢它而不是人们在这里提出的更专业的帮助函数。
我用
list.Where (r=>r.value == value).DefaultIfEmpty().First()
如果不匹配,结果将为 null,否则返回其中一个对象
如果您想要列表,我相信离开 First() 或调用 ToList() 将提供列表或 null。
它 null 将返回 true
enter public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
try
{
return enumerable?.Any() != true;
}
catch (Exception)
{
return true;
}
}
代码在这里
只需添加 using System.Linq
并在您尝试访问 IEnumerable
中的可用方法时看到神奇的发生。添加它将使您能够像这样简单地访问名为 Count()
的方法。请记住在调用 count()
之前检查 null value
:)
this
放在那里——我认为假定在null
上调用的扩展方法是丑陋设计的标志。.Any()
是在IEnumerable<T>
(或IQueryable<T>
上运行的扩展方法,尽管这是不同的场景)。这样做消耗序列,至少部分(尽管这仍然意味着它被消耗) - 它可能只需要读取一个元素(尤其是在没有谓词的情况下)。因此,由于序列 (IEnumerable<T>
) 不需要是可重复的,可能就是这样。没有谓词的Any()
基本上 等同于foreach(var x in sequence) { return true; } return false;
- 尽管它使用GetEnumerator()
等而不是编译器语法