在空对象上调用Any()时,它会在 C# 中引发 ArgumentNullException。如果对象为空,则肯定没有“任何”,它可能应该返回 false。
为什么 C# 会这样?
在空对象上调用Any()时,它会在 C# 中引发 ArgumentNullException。如果对象为空,则肯定没有“任何”,它可能应该返回 false。
为什么 C# 会这样?
Any()正在问:“这个盒子里有什么东西吗?”
如果盒子是空的,答案显然是否定的。
但是如果一开始就没有盒子,那么这个问题就没有意义了,函数就会抱怨:“你到底在说什么?没有盒子。”
当我想将丢失的集合视为空集合时,我使用以下扩展方法:
public static IEnumerable<T> OrEmpty<T>(this IEnumerable<T> sequence)
{
return sequence ?? Enumerable.Empty<T>();
}
这可以与所有 LINQ 方法结合使用foreach,而不仅仅是.Any().
使用现代 C#,您可以通过如下简单检查轻松处理 OP 场景:
List<string> foo = null;
if (foo?.Any() ?? false)
{
DoStuff();
}
这有点像AnyOrDefault(bool default)OP 期望Any()扩展方法执行的蹩脚实现。
你可以很容易地把它变成这样的扩展:
public static bool HasItems<T>(this IEnumerable<T> source)
{
return (source?.Any() ?? false);
}
老实说,我真的不喜欢这个名字AnyOrDefault,因为传递默认值是没有意义的(默认值 true 可能对以后阅读代码的人来说是非常卑鄙的)。HasItems按照评论中的建议重命名为。这是一个更好的名字!
在处理引用类型时,null值在语义上与“空”值不同。
字符串null与 不同string.Empty,并且 anull IEnumerable<T>与 Enumerable.Empty<T>(或该类型的任何其他“空”可枚举)不同。
如果Any不是扩展方法,则调用它null会导致NullReferenceException. 由于它是一种扩展方法,因此抛出一些异常(尽管不是必需的)是一个好主意,因为它保留了尝试调用方法的众所周知的语义null:BOOM!
Any()是一个扩展方法,所以this实际上是作为方法的第一个参数传递的。在这种情况下,它抛出ArgumentNullExceptionis thisis 是可以理解的null。
您可以事先自行执行检查:
bool hasAny = yourData == null ? false : yourData.Any(yourPredicate);
因为 Any() 它是这样的扩展方法:
public static bool Any(this IEnumerable enumerable)
{
if (enumerable == null)
throw ArgumentNullException("enumerable");
...
}
该Any方法针对 an 运行并告诉您Enumerable 中IEnumerable是否有任何项目。如果您不给它任何枚举,那么 ArgumentNullException 是合理的:没有(匹配)元素的集合与没有集合不同。
正如其他人已经提到的,Any检查序列是否包含元素。它不会阻止您传递null值(首先可能是什么错误)。
Enumerable类中的每个扩展方法都会抛出一个ArgumentNullExceptionif the sourceis null。加入ArgumentNullExceptions扩展实际上是一种很好的做法。
Any()是一个扩展方法,ArgumentNullException如果源为空则抛出。你会什么都不做吗?通常,最好获得一些关于代码中正在发生的事情的明确指示,而不是默认值。
但这并不意味着它不能那样。如果您知道自己在做什么,请编写自己的自定义实现。
我只是想与您分享一些我公司正在遵循的实用建议。我们编写与私有 NuGet 共享的自定义包,这些包在我们的产品中广泛使用。检查列表是否为空/空是非常频繁的,因此我们决定编写我们的实现以Any使我们的代码更短更简单。