【发布时间】:2019-06-02 14:40:38
【问题描述】:
我有一个方法,Foo,它接受一个字符串。如果字符串为空,它会做一些事情,如果不是,它会做一些其他事情(null 是一个有效值)。然后它返回相同的字符串。
这是在 C# 8.0 中具有可空引用类型已禁用的 Foo:
string Foo(string s)
{
// Do something with s.
return s;
}
void Bar()
{
string s = "S";
string s2 = Foo(s);
string n = null;
string n2 = Foo(n);
}
启用可空引用类型后,string n = null 会发出警告。这是有道理的,因为 string 不再可以为空。我将其类型转换为string?:
void Bar()
{
string s = "S";
string s2 = Foo(s);
string? n = null; // X
string? n2 = Foo(n);
}
现在Foo(n) 警告我 Foo 对可空字符串的新厌恶。这也很有意义 - Foo 应该接受一个可为空的字符串,因为它同时支持空值和非空值。我更改了它的参数,因此返回类型为string?:
string? Foo(string? s)
{
// Do something with s.
return s;
}
这次是 string s2 = Foo(s),抱怨 Foo 返回了 string?,而我试图将其分配给 string。
有没有办法让流分析理解这样一个事实,即当我向 Foo 提供 string(而不是 string?)时,它的返回值不能为空?
【问题讨论】:
-
这可以在单一方法中实现吗?没有。
-
虽然理论上可以编写一个流分析器来跟踪“这种方法从输入到输出是否保留了可空性?”在实践中,通常情况并非如此。
-
我希望代码合同已经起飞。
-
是的,我也是,但他们确实陷入了尴尬的境地。库和重写器足够强大,以至于我们觉得我们没有充分的理由将其集成到语言中,但用户的观点是它们并没有那么引人注目,以至于人们觉得如果不这样做,成本就值得收益有“免费”的语言。我对这一切的结果感到有些遗憾。
-
我们正在考虑一些属性来帮助解决这种情况。此特定场景将使用
[NullInNullOut](名称尚未确定)。 github.com/dotnet/roslyn/issues/26761
标签: c# c#-8.0 nullable-reference-types