【问题标题】:Check if list is null before using linq在使用 linq 之前检查列表是否为空
【发布时间】:2020-03-04 20:33:24
【问题描述】:

使用 LINQ 我想检查 myList != null 是否,然后执行 Where。

我知道我会写

if (myList != null { myList.Where(p => p.x == 2 && p.y == 3); }

但我想使用:myList?.Where(p => p.x == 2 && p.y == 3);

这行得通吗?

如果没有,您还知道哪些其他优雅的解决方案?

【问题讨论】:

  • “LINQ 查询”是指查询语法吗? from x in y where z select w 语法。
  • 1.使列表永远不可能为 null 或 2。myList?.Where(p => p.x == 2 && p.y == 3) ?? DEFAULT_VALUE; 其中 DEFAULT_VALUE 可能是一个空列表。
  • 请显示您的列表结构
  • 我的问题可能不清楚。我在问 myList?.Where() 是否是一个有效的表达式,如果不是,还有什么替代方法
  • “我在问 myList?.Where() 是否是一个有效的表达式” - 你的 IDE 标记了吗?你的编译器有没有报错?运行时是否抛出异常?它没有做你期望它做的事吗?如果所有这些的答案都是“否”,那么它就是“有效”。

标签: c# linq null-check


【解决方案1】:

是的,list?.Where(i => i > 1) 是一个合法的表达式,称为“空传播运算符”。

关于使用空传播运算符的问题是你会开始写这样的代码

var result = list?.Where(i => i > 1)?.Select(i => i * 2)?.Where(i => i % 2 == 0)?.ToList();
// result can be null and still requires check for null

.. 你还知道哪些优雅的解决方案?

其他优雅的解决方案是确保每当函数返回一个集合时,它永远不会返回null,而是一个空集合。

这样的约定将使您的代码更易于阅读和理解代码的实际意图,使其易于测试(要测试的测试用例更少),更少的“嘈杂的空检查”。

请注意,LINQ 扩展方法永远不会返回 null

如果您使用的库为集合返回 null 但您无权访问代码 - 将null“转换”为空集合并继续用作有效集合。

var checkedList = givenList ?? Enumerable.Empty<int>();
checkedList.Where(i => i > 1).ToList();

如果您发现自己经常这样做,请创建一个扩展方法。

public IEnumerable<T> EmptyIfNull(this IEnumerable<T> source)
{
    return source ?? Enumerable.Empty<T>();     
}

用法

var result = givenList.EmptyIfNull().Where(i => i > 1).ToList();

【讨论】:

    【解决方案2】:

    如果您使用 C# 6 / Visual Studio 2013 或更高版本构建,您可以编写:

    var result = myList?.Where(p => p.x == 2 && p.y == 3);
    

    因此,如果 myListnull,则不会评估 Where 并且 result 将是 null,否则属于结果查询的类型(IEnumerable&lt;T&gt;IQueryable&lt;T&gt;)。

    Null-conditional operators

    你也可以写:

    var result = myList?.Where(p => p.x == 2 && p.y == 3) ?? someValue;
    

    所以如果myListnull,则result 将由someValue 分配。

    Null-coalescing operator

    你可以在Project Settings &gt; Build &gt; Advanced options &gt; Language version查看选项。

    【讨论】:

    • 小扩展var result = myList?.Where(p =&gt; p.x == 2 &amp;&amp; p.y == 3) ?? someDefault;会在你的列表为空时返回一个合适的默认值
    • 如果无法使用 C# 6,也可以这样做:(myList ?? someDefault).Where(...),它不需要使用较新的 null 条件。