【发布时间】:2020-12-29 08:14:19
【问题描述】:
考虑一下这个不太安全的 sn-p:
private object? _obj;
private void Dummy()
{
if (this._obj == null)
{
this.Create();
}
Console.WriteLine(this._obj!.ToString()); //note the null-forgiving operator
}
private void Create()
{
this._obj = new object();
}
虽然_obj字段明确保证不为空,但检查器无法理解。清除警告的解决方案是添加 null-forgiving 运算符,尽管我希望避免或谨慎使用它。
修改后的 sn-p 导致了更安全的模式和完全可检查的代码:
private void BetterDummy()
{
this._obj ??= this.BetterCreate();
Console.WriteLine(this._obj!.ToString());
}
private object BetterCreate()
{
return new object();
}
但是,我可能忘记从它所在的位置删除!(假设有很多这样的地方)。该操作员禁止对该点进行检查,因此我想将代码设置为最佳。
我想知道是否有一个选项可以突出显示/警告“不再有用”的 null-forgiving 运算符,以便快速找到它们并将其从代码中删除。
【问题讨论】:
-
由于
_obj是一个字段而不是本地属性,如何保证另一个线程不会使您保证的null分配和Console.WriteLine之间的字段为空? -
@Knoop 你是对的。我的原始代码是真正安全的,因为有一个信号量锁定它。但是,我的意思是对第一个 sn-p 的“更安全”。
-
“真正安全”很遗憾,这不是真的。
semaphore只有在每个人都玩得很好的情况下才有效。即使您通过属性等强制它,人们仍然可以作弊并通过反射访问private支持字段。保证是一件非常复杂的事情,您似乎发现了一个编译器似乎有点困惑的场景(不会警告删除它,但如果它被删除也不会警告添加它),但 imo 正确的方法不会是告诉你删除它,因为在这种情况下没有完全的保证,即使使用信号量也是如此。 -
@Knoop 不关注并发或类似问题:静态检查不考虑这一点。我说的是那个,而不是线程安全:上面只是一个例子,但它可能完全不同。
-
我知道 Resharper 会在不需要的地方突出显示操作符的用法。并且可以进行重构以删除不需要的部分。
标签: c# nullable static-analysis