【问题标题】:Why don't the following expressions trigger "The result of the expression is always false ..."?为什么下面的表达式不触发“表达式的结果总是假的......”?
【发布时间】:2021-11-18 05:41:50
【问题描述】:

我在 VS Code 中使用以下表达式,我注意到在某些情况下 VS Code 会显示警告。

if(true==null)
{}
else
{}

表达式的结果总是false,因为值类型 bool 永远不等于 null 类型的 bool?

但是,如果我编写以下内容,VS Code 不会抱怨。

if(new Foo()==null)
{}
else
{}

Foo 是一个类。

问题

为什么上面的表达式不产生The result of the expression is always false ...

【问题讨论】:

  • 是否保证new Foo()总是返回非空引用?
  • 撇开诸如重载运算符之类的奇特事物不谈,通常 C# 编译器实际上并不会非常努力地确定条件始终为truefalse,只是基础知识。例如 int x = 0; if (x < 3) { Console.WriteLine(...); }x 是本地的也不会触发任何警告,即使(例如)几乎所有 C 编译器都会发出警告。
  • @JeroenMostert 这正是静态分析器工具介入并告诉用户“嘿,您将此值分配给变量并且从不更改它。将其设为常量,或仅输入值你在任何地方都在使用它你!”
  • @Logarr:当然,除了编译器按定义执行静态分析,所以几乎所有的编译器也会检测到这样的事情。专用的静态分析工具往往会更进一步,检测编译器中没有内置的东西(出于速度的原因,或者因为错误不常见或不够清晰,如果你不是执行主观的“最佳实践”)。 C# 编译器在这里的不同寻常之处在于它甚至无法检测到使用无意常量的最简单情况。

标签: c#


【解决方案1】:

首先,静态分析并不完美,警告是为了保护您免受自己的伤害,在很多情况下您可能 strong> 知道得更好。

但是,new Foo() 仍然可以等于 null ...如果有脏小手指的人决定覆盖等式运算符:/

考虑以下阴险的例子:

public class Foo
{
   public static bool operator ==(Foo x, Foo y) => true;
   public static bool operator !=(Foo x, Foo y) => false;
}

...

if (new Foo() == null)
   Console.WriteLine("Is null");
else
   Console.WriteLine("Is not null");

输出

Is null

但是我们可以使用is 运算符来确保:

if (new Foo() is null)
   Console.WriteLine("Is null");
else
   Console.WriteLine("Is not null");

输出

Is not null

基本上编译器会将上面的转换成下面的,否定任何操作符效果:

if ((object)new Foo() == null)

正如@Jeroen Mostert 所指出的,如果您使用的是普通的 Visual Studio 或 Code,这仍然不会被标记为始终为 false。不过,如果您使用的是 Resharper,它可能会。

简而言之,编译器实际上只对这些类型的事物进行基本的静态检查,在某些情况下它要么无法弄清楚,要么决定不担心遵循复杂的分支来计算 if 和表达式实际上总是正确与否。

【讨论】:

  • 尽管重载运算符是new 可能不是null 的潜在情况,但值得指出的是,new Foo() is null 仍然未被检测为始终为true 的表达式,所以没有警告并不是因为编译器足够聪明来考虑这种极端情况,而是因为它基本上选择不打扰。
  • @JeroenMostert 更新和归属
猜你喜欢
  • 2013-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-31
  • 2021-12-28
  • 2021-04-01
  • 1970-01-01
  • 2012-05-28
相关资源
最近更新 更多