69

在空对象上调用Any()时,它会在 C# 中引发 ArgumentNullException。如果对象为空,则肯定没有“任何”,它可能应该返回 false。

为什么 C# 会这样?

4

8 回答 8

153

Any()正在问:“这个盒子里有什么东西吗?”

如果盒子是空的,答案显然是否定的。

但是如果一开始就没有盒子,那么这个问题就没有意义了,函数就会抱怨:“你到底在说什么?没有盒子。”


当我想将丢失的集合视为空集合时,我使用以下扩展方法:

public static IEnumerable<T> OrEmpty<T>(this IEnumerable<T> sequence)
{
    return sequence ?? Enumerable.Empty<T>();
}

这可以与所有 LINQ 方法结合使用foreach,而不仅仅是.Any().

于 2012-07-18T09:30:19.833 回答
60

使用现代 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按照评论中的建议重命名为。这是一个更好的名字!

于 2017-10-11T14:19:29.380 回答
55

在处理引用类型时,null值在语义上与“空”值不同。

字符串null与 不同string.Empty,并且 anull IEnumerable<T>Enumerable.Empty<T>(或该类型的任何其他“空”可枚举)不同。

如果Any不是扩展方法,则调用它null会导致NullReferenceException. 由于它一种扩展方法,因此抛出一些异常(尽管不是必需的)是一个好主意,因为它保留了尝试调用方法的众所周知的语义nullBOOM!

于 2012-07-18T09:30:06.590 回答
5

Any()是一个扩展方法,所以this实际上是作为方法的第一个参数传递的。在这种情况下,它抛出ArgumentNullExceptionis thisis 是可以理解的null

您可以事先自行执行检查:

bool hasAny = yourData == null ? false : yourData.Any(yourPredicate);
于 2012-07-18T09:29:18.660 回答
3

因为 Any() 它是这样的扩展方法:

public static bool Any(this IEnumerable enumerable)
{
    if (enumerable == null)
        throw ArgumentNullException("enumerable");
    ...
}
于 2012-07-18T09:36:20.453 回答
2

Any方法针对 an 运行并告诉您Enumerable 中IEnumerable是否有任何项目。如果您不给它任何枚举,那么 ArgumentNullException 是合理的:没有(匹配)元素的集合与没有集合不同。

于 2012-07-18T09:28:41.773 回答
1

正如其他人已经提到的,Any检查序列是否包含元素。它不会阻止您传递null值(首先可能是什么错误)。

Enumerable中的每个扩展方法都会抛出一个ArgumentNullExceptionif the sourceis null。加入ArgumentNullExceptions扩展实际上是一种很好的做法

于 2012-07-18T09:36:33.230 回答
0

Any()是一个扩展方法,ArgumentNullException如果源为空则抛出。你会什么都不做吗?通常,最好获得一些关于代码中正在发生的事情的明确指示,而不是默认值。

但这并不意味着它不能那样。如果您知道自己在做什么,请编写自己的自定义实现。

我只是想与您分享一些我公司正在遵循的实用建议。我们编写与私有 NuGet 共享的自定义包,这些包在我们的产品中广泛使用。检查列表是否为空/空是非常频繁的,因此我们决定编写我们的实现以Any使我们的代码更短更简单。

于 2019-10-09T07:13:13.077 回答