C# 中的 Bool 对我来说有些不清楚

Bool in C# works something unclear for me

提问人:DeepBlue 提问时间:7/18/2023 最后编辑:marc_sDeepBlue 更新时间:7/18/2023 访问量:80

问:

下面是一个 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 :)

C# 布尔表达式 boolean-operations

评论

4赞 Etienne de Martel 7/18/2023
按位运算符 () 未短路。&
0赞 DeepBlue 7/19/2023
嘿!谢谢哥们!每天20个小时的工作和几个小时的学习让我注意力不集中。多亏了你的帮助和你的时间,我弄清楚了我的错误在哪里。再次感谢!

答:

3赞 Corey 7/18/2023 #1

基本原因是按位运算符不会短路,而逻辑运算符会短路。正如您在变量名称中指出的那样,您至少知道这一事实。&&&

(目前尚不清楚您是否了解后增量运算符的工作原理。它获取操作数的值 (, value: ),递增操作数,然后返回递增前的值。因此,在这两种情况下,比较结果均为 false。这可能与问题密切相关,也可能与问题无关。++firstNumber0> 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 。thirdNumber1resulttrue

评论

0赞 Jonathan Dodds 7/18/2023
我不会说加法运算符不会短路。短路不适用于加法。同样,短路也不适用于按位 AND 运算符。这似乎是吹毛求疵,但我认为强调按位 AND 和逻辑 AND 彼此之间的不同程度是有帮助的。+&
0赞 Corey 7/18/2023
@JonathanDodds我很困惑......是的,我将按位称为算术运算符,这在技术上是不正确的。但我根本没有说任何关于算术运算符的事情。&+
0赞 Jonathan Dodds 7/18/2023
是的,你没有提到运营商。关于“短路”,操作员更像是操作员,而不是操作员。+&+&&
0赞 Corey 7/18/2023
@JonathanDodds 没错,我根本没有提到加法。这就是为什么我对你会提出它感到困惑。你是对的,“短路不适用于加法”,是的,这与按位运算符相同,但它与我的答案或问题完全无关。这就是让我感到困惑的地方。&
0赞 Jonathan Dodds 7/19/2023
&运算符不会短路”,就像你在回答中所做的那样,就像写运算符不会短路一样。+