是否有一种方便的方法来过滤C#8.0可空引用的序列,仅保留非空值? [英] Is there a convenient way to filter a sequence of C# 8.0 nullable references, retaining only non-nulls?
问题描述
我有这样的代码:
IEnumerable<string?> items = new [] { "test", null, "this" };
var nonNullItems = items.Where(item => item != null); //inferred as IEnumerable<string?>
var lengths = nonNullItems.Select(item => item.Length); //nullability warning here
Console.WriteLine(lengths.Max());
我如何以一种方便的方式编写此代码,例如:
How can I write this code in a convenient way such that:
- 没有可空性警告,因为类型
nonNullItems
被推断为IEnumerable<string>
. - 我不需要添加诸如
item!
之类的未经检查的不可为空的断言(因为我想从编译器的健全性检查中受益,而不是依靠我成为无错误的编码器) - 我不添加运行时检查的不可为空的断言(因为在代码大小和运行时,这都是毫无意义的开销,并且如果人为错误的发生晚于理想情况).
- 解决方案或编码模式可以更普遍地应用于其他可为空的引用类型的项目序列.
- There is no nullability warning, because the type
nonNullItems
is inferred asIEnumerable<string>
. - I don't need to add unchecked non-nullability assertions like
item!
(because I want to benefit from the compilers sanity checking, and not rely on me being an error-free coder) - I don't add runtime checked non-nullability assertions (because that's pointless overhead both in code-size and at runtime, and in case of human error that fails later than ideal).
- The solution or coding pattern can apply more generally to other sequences of items of nullable-reference type.
我知道这种解决方案,它利用了C#8.0编译器中的流敏感型输入,但是它...不是那么漂亮,主要是因为它是如此的冗长和嘈杂:
I'm aware of this solution, which leverages the flow-sensitive typing in the C# 8.0 compiler, but it's.... not so pretty, mostly because it's so long and noisy:
var notNullItems = items.SelectMany(item =>
item != null ? new[] { item } : Array.Empty<string>())
);
还有更好的选择吗?
推荐答案
我认为您必须以一种或另一种方式来帮助编译器.调用.Where()
绝不返回非空值.也许Microsoft可以添加一些逻辑来确定像您这样的基本方案,但是AFAIK目前还不是这种情况.
I think you'll have to help the compiler in either one way or another. Calling .Where()
is never safe of returning not-null. Maybe Microsoft could add some logic to determine basic scenarios like yours, but AFAIK that's not the situation right now.
但是,您可以编写一个像这样的简单扩展方法:
However, you could write a simple extension method like that:
public static class Extension
{
public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> o) where T:class
{
return o.Where(x => x != null)!;
}
}
这篇关于是否有一种方便的方法来过滤C#8.0可空引用的序列,仅保留非空值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!