提问人:DeepBlue 提问时间:7/18/2023 最后编辑:marc_sDeepBlue 更新时间:7/18/2023 访问量:80
C# 中的 Bool 对我来说有些不清楚
Bool in C# works something unclear for me
问:
下面是一个 C# 代码示例。我不明白为什么在第一种情况下我们会有 1 而不是 0。
为什么它返回 1?
static void Main(string[] args)
{
int firstNumber = 0;
bool simpleLogicResult = true & false & (firstNumber++ > 0);
Console.WriteLine($"firstNumber = {firstNumber}");
int secondNumber = 0;
bool shortCircuitResult = true && false && (secondNumber++ > 0);
Console.WriteLine($"secondNumber = {secondNumber}");
// Delay
Console.ReadKey();
}
我期望 0 而不是 1 :)
答:
基本原因是按位运算符不会短路,而逻辑运算符会短路。正如您在变量名称中指出的那样,您至少知道这一事实。&
&&
(目前尚不清楚您是否了解后增量运算符的工作原理。它获取操作数的值 (, value: ),递增操作数,然后返回递增前的值。因此,在这两种情况下,比较结果均为 false。这可能与问题密切相关,也可能与问题无关。++
firstNumber
0
> 0
编译器可以在编译过程中计算所有术语,因为所有值要么是常量,要么是已知的。它可以自由地减少表达,而这正是实际发生的情况。
让我们看看你的前两行:
int firstNumber = 0;
bool simpleLogicResult = true & false & (firstNumber++ > 0);
这里正在发生两件事。
第一种是编译第二行中的所有三个项,生成一组已知值或常量值和一个递增运算。必须对这三个因素进行全面评估,包括所有副作用,因为按位运算符不会使操作数短路。&
其次,编译器进行表达式简化,尽可能预先计算答案。由于计算中的所有项都是常数,因此可以在编译时预先计算表达式,并保留所有副作用(在本例中为递增操作)。
当您将编译的 IL 反转回 C# 时,它产生的结果是这样的:
int firstNumber = 0;
firstNumber++;
bool simpleLogicResult = false;
现在,您的第二个计算使用运算符:&&
int secondNumber = 0;
bool shortCircuitResult = true && false && (secondNumber++ > 0);
第一次操作会产生一个恒定的假值,因此由于短路,不会计算第三项。因此,当编译器处理此操作时,它不必像上面的算术运算那样对增量操作进行排队。true && false
所以我们在编译和反编译后得到的结果是这样的:
int secondNumber = 0;
bool shortCircuitResult = false;
对于奖励点,预增量运算符在这种特定情况下将产生完全相同的结果,因为您在表达式中为按位表达式和逻辑表达式都包含了一个术语。但是,如果我们更改您的表达式,结果会有所不同:++
false
&
&&
int thirdNumber = 0;
bool result = true & (++thirdNumber > 0);
在这种情况下,生成的降低代码(从生成的 IL 中反编译)为:
int thirdNumber = 0;
bool result = ++thirdNumber > 0;
可悲的是,对于编译器来说,预增量似乎有点难以优化,但结果是相同的:is 和 is 。thirdNumber
1
result
true
评论
+
&
&
+
+
&
+
&&
&
&
位运算符不会短路”,就像你在回答中所做的那样,就像写运算符不会短路一样。+
上一个:单子的应用
下一个:布尔逻辑和 For 循环
评论
&