检查后 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
变量和 if
中 Length
的取消引用。第二个我可以通过添加一个像这样的该死的(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)
{
...
}
}
查看此示例:
var list = new List<string?>();
foreach (string item in list.Where(i => i != null))
{
if (item.Length == 2)
{
...
}
}
在此示例中,我在两个地方获得了可能的空引用。 foreach
变量和 if
中 Length
的取消引用。第二个我可以通过添加一个像这样的该死的(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)
{
...
}
}