检查后 Foreach 变量不为空仍会发出警告

Foreach variable not null after check still gives warning

查看此示例:

var list = new List<string?>();

foreach (string item in list.Where(i => i != null))
{
    if (item.Length == 2)
    {
        ...
    }
}

在此示例中,我在两个地方获得了可能的空引用。 foreach 变量和 ifLength 的取消引用。第二个我可以通过添加一个像这样的该死的(null-forgiving)运算符来轻松修复:item!.Length

有没有办法对第一个做同样的事情?我知道我可以将它标记为可为空的字符串并再次检查但是,我已经检查过了。

当您使用 Where 应用过滤时,您消除了所有空值,但这不会更改值的类型。
您只需要将过滤后的结果转换为正确的类型即可:

foreach (string item in list.Where(i => i != null).Select(x => x!))

不幸的是,Where 谓词不会修改调用者对可枚举项中的项目是否为 null 的看法。

由于使用了额外的 Select 调用, 涉及额外的运行时开销。

您可以通过此扩展方法避免这种开销:

public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> source) where T : class
{
    foreach (T? item in source)
    {
        if (item != null)
            yield return item;
    }
}

您的代码将变为:

foreach (string item in list.WhereNotNull())
{
    if (item.Length == 2)
    {
        ...
    }
}