【发布时间】:2021-12-10 13:42:22
【问题描述】:
考虑以下 xUnit 测试(这是我遇到的最流行和最烦人的案例):
public class UnitTest1
{
[Fact]
public async Task Test1()
{
var result = await this.FindAsync();
Assert.NotNull(result); // Line 1
Assert.Equal(3, result.Length); // Line 2: Null warning here
Assert.Equal("yes", result.ToLower()); // Line 3
}
// I use async to demonstrate a shortcoming of workaround
async Task<string?> FindAsync()
{
return await Task.FromResult("Yes");
}
}
由于 xUnit 还没有 [NotNull] 注释,编译器不知道 result 从那里开始不能是 null。但是,如果我在第 1 行将其标记为“not null”,则它不起作用:
Assert.NotNull(result!); // Tooltip says "result" is not null here
Assert.Equal(3, result.Length); // But here it says "result" may be null
这些解决方法有效,但有缺点:
// Mark as not null at the assignment:
// - Has to add parentheses in many cases
// - Does not work if it may actually be null
var result = (await this.FindAsync())!;
// Mark on the first usage, like at line 2:
// This has to be at the first line.
// If you move code around or remove it, you get the warning back and have to move the ! around
Assert.Equal(3, result!.Length);
如果我将! 放在第 1 行 Assert.NotNull(result!);,为什么它不能“正常”工作?这是编译器错误吗?
【问题讨论】:
-
第 1 行没有警告,所以
!没有什么可以抑制的,所以它没有效果 -
@canton7 虽然您可能是对的,但这使得操作员如此违反直觉。当我使用
!时,我希望编译器知道从那里开始,它不为空,而不仅仅是“不要在此处发送警告” -
这不是它的作用。它用于代码中的特定点以抑制该点的可为空警告。这不是一个注释,意思是“这个对象不能在这里为空”,它的意思是“闭嘴关于这里生成的这个特定警告”
-
@LukeVo:文档正在讨论您放置
!的特定表达式。它没有说明“以及今后的所有表达方式”。 -
第 3 行没有警告,因为编译器知道,如果
result是null,第 2 行会抛出NullReferenceException导致第 3 行无法访问
标签: c# .net null roslyn nullable-reference-types