C#中针对null和Any()的快捷方式

24

在C#中,我经常需要做这件事

if(x.Items!=null && x.Items.Any())
{ .... }

在集合上有没有快捷方式?


1
你可以按照这里所述的方式创建你的扩展方法:https://dev59.com/lnVD5IYBdhLWcg3wQJKT - Farhad Jabiyev
1
那么以这种方式检查有什么问题吗? - Ehsan Sajjad
@Ehsan 如果你正在监控分支覆盖率,那么它会使其变得复杂,并且通常只会得到 null 或空集合中的一个情况。 - Rup
2
你应该避免一开始就有空集合。确保所有的集合变量都始终被赋予一个值,即使这个值是空的,这样就不需要后来检查它们是否为空了。 - Servy
1
@Jcl 你是否也会检查 string Foo() 的结果类型是否为 string? :) 如果契约规定“永远不会返回null”,那么您就不应该检查null——在出现null的情况下,唯一有效的操作是完全失败操作/进程... - Alexei Levenkov
显示剩余8条评论
2个回答

82

C# 6中,您将能够编写:

if (x.Items?.Any() == true)

在那之前,你总是可以编写自己的扩展方法:

public static bool NotNullOrEmpty<T>(this IEnumerable<T> source)
{
    return source != null && source.Any();
}

那么只需使用:

if (x.NotNullOrEmpty())

将名称更改以适合您的口味,例如NullSafeAny可能更符合您的口味 - 但我肯定会在名称中明确指出,即使x为null也是有效的调用。


2
在C# 6的示例中,你必须要写 == true 吗?还是 if (x.Items?.Any()) 就可以了?如果条件成立,程序会进入该代码块。这样做可能只能省下几个按键,而加上 == true 可能会更清晰明了。 - Ctrl_Alt_Defeat
13
@Ctrl_Alt_Defeat:不,x.Items?.Any() 的类型是 Nullable<bool>,所以你需要在这里加上 == true - 这意味着如果 x.Items 返回 null,条件将 不会 满足。这与 if (x.Items?.Any != false) 不同,如果 x.Items 为 null,则结果将为 null,它不等于 false,所以条件将被满足。 - Jon Skeet
1
如果您真的想因其他原因避免可空性: x.Items?.Any() ?? false - Adam Bezverkov
1
@JonSkeet 正确,我认为我只是不喜欢在处理可空类型时使用 == true 语句。而且那个 (myVar?.Any()).HasValue 也让我感觉不对劲。我个人更喜欢写得更详细一些,但阅读起来更容易。 - Sergey Zykov
3
@JustFair:是的,我非常明确地指的是C#而不是.NET。你可以在.NET 2.0中做到这一点——如果你使用的是C# 6或更高版本的编译器。但是,使用C# 5是做不到的。语言和框架版本是不同的。 - Jon Skeet
显示剩余10条评论

1
我还会检查列表中的项目,以确保列表不仅包含所有空对象;因此,对Jon Skeet的答案进行了改进:
public static bool NotNullOrEmpty<T>(this IEnumerable<T> source)
{
    return source != null && !source.All(x => x == null);
}

个人而言,我觉得对于名称很令人困惑(肯定不等同于 OP 的代码)。我希望能找到如果列表本身不为空且列表不为空,则不检查所有项目是否为空。此外,这更可能枚举整个可枚举对象,因此性能可能会受到列表的影响。当然,如果适合您,您可以自由地进行检查,但作为通用解决方案(例如,在扩展方法库中),我强烈建议反对它。 - Jcl
是的,这正是我所期望的。不仅仅是在Jon Skeet的回答中,也包括OP的代码。 - Jcl
我认为只有一个空项的列表应该被视为空列表。你觉得呢? - alsafoo
1
foreach(var x in myList) { if(x == null) DoThis(); else DoThat(); }。如果您使用自己的方法来检查是否应该“foreach”,那么DoThis()将永远不会被调用。想象一下,您的列表来自数据库,而null值意味着“此订单未付款”,因此您“可能”需要对null值采取行动(这不是最好的例子,但说明了问题)。对于某些实现,空值可能意味着某些内容...正如我所说,如果它适用于-您-的类型,那么很好,但作为-通用-实现,它具有潜在的缺点。 - Jcl
2
当然,你可以将自己的扩展方法命名为 NotNullAndAnyHasValue() 或其他名称,但我不会用这个替换其他扩展方法。 - Jcl
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接