布尔逻辑运算符 - AND、OR、NOT、XOR

逻辑布尔运算符使用 bool 操作数执行逻辑运算。 运算符包括一元逻辑非 (!)、二元逻辑 AND (&)、OR (|) 以及异或 (^),二元条件逻辑 AND (&&) 和 OR (||)。

对于整型数值类型的操作数,&|^ 运算符执行位逻辑运算。 有关详细信息,请参阅位运算符和移位运算符

逻辑非运算符 !

一元前缀 ! 运算符计算操作数的逻辑非。 也就是说,如果操作数的计算结果为 true,它生成 false;如果操作数的计算结果为 false,它生成 true

bool passed = false;
Console.WriteLine(!passed);  // output: True
Console.WriteLine(!true);    // output: False

一元后缀 ! 运算符为 null 包容运算符

逻辑“与”运算符 &

& 运算符计算操作数的逻辑与。 如果 x & ytrue 的计算结果都为 x,则 y 的结果为 true。 否则,结果为 false

& 运算符总是计算两个操作数。 当左侧操作数的计算结果为 false 时,运算结果为 false,而与右侧操作数的值无关。 但是,即使在这种情况下,也会计算右侧操作数。

在下面的示例中,& 运算符的右侧操作数是方法调用,无论左侧操作数的值如何,都会执行方法调用:

bool SecondOperand()
{
    Console.WriteLine("Second operand is evaluated.");
    return true;
}

bool a = false & SecondOperand();
Console.WriteLine(a);
// Output:
// Second operand is evaluated.
// False

bool b = true & SecondOperand();
Console.WriteLine(b);
// Output:
// Second operand is evaluated.
// True

条件逻辑 AND 运算符&& 也计算操作数的逻辑 AND,但如果左侧操作数的计算结果为 false,它就不会计算右侧操作数。

对于整型数值类型的操作数,& 运算符计算其操作数的位逻辑 AND。 一元 & 运算符是 address-of 运算符

逻辑异或运算符 ^

^ 运算符计算操作数的逻辑异或(亦称为“逻辑 XOR”)。 如果 x ^ y 计算结果为 truex 计算结果为 true,或者 y 计算结果为 falsex 计算结果为 false,那么 y 的结果为 true。 否则,结果为 false。 也就是说,对于 bool 操作数,^ 运算符的计算结果与不等运算符!= 相同。

Console.WriteLine(true ^ true);    // output: False
Console.WriteLine(true ^ false);   // output: True
Console.WriteLine(false ^ true);   // output: True
Console.WriteLine(false ^ false);  // output: False

对于整型数值类型的操作数,^ 运算符计算其操作数的位逻辑异或

逻辑或运算符 |

| 运算符计算操作数的逻辑或。 如果 x | ytrue 的计算结果为 x,则 y 的结果为 true。 否则,结果为 false

| 运算符总是计算两个操作数。 当左侧操作数的计算结果为 true 时,运算结果为 true,而与右侧操作数的值无关。 但是,即使在这种情况下,也会计算右侧操作数。

在下面的示例中,| 运算符的右侧操作数是方法调用,无论左侧操作数的值如何,都会执行方法调用:

bool SecondOperand()
{
    Console.WriteLine("Second operand is evaluated.");
    return true;
}

bool a = true | SecondOperand();
Console.WriteLine(a);
// Output:
// Second operand is evaluated.
// True

bool b = false | SecondOperand();
Console.WriteLine(b);
// Output:
// Second operand is evaluated.
// True

条件逻辑 OR 运算符|| 也计算操作数的逻辑 OR,但如果左侧操作数的计算结果为 true,它就不会计算右侧操作数。

对于整型数值类型的操作数,| 运算符计算其操作数的位逻辑 OR

条件逻辑“与”运算符 &&

条件逻辑与运算符 &&(亦称为“短路”逻辑与运算符)计算操作数的逻辑与。 如果 x && ytrue 的计算结果都为 x,则 y 的结果为 true。 否则,结果为 false。 如果 x 的计算结果为 false,则不计算 y

在下面的示例中,&& 运算符的右侧操作数是方法调用,如果左侧操作数的计算结果为 false,就不执行方法调用:

bool SecondOperand()
{
    Console.WriteLine("Second operand is evaluated.");
    return true;
}

bool a = false && SecondOperand();
Console.WriteLine(a);
// Output:
// False

bool b = true && SecondOperand();
Console.WriteLine(b);
// Output:
// Second operand is evaluated.
// True

逻辑 AND 运算符& 也计算操作数的逻辑 AND,但始终计算两个操作数。

条件逻辑或运算符 ||

条件逻辑或运算符 ||(亦称为“短路”逻辑或运算符)计算操作数的逻辑或。 如果 x || ytrue 的计算结果为 x,则 y 的结果为 true。 否则,结果为 false。 如果 x 的计算结果为 true,则不计算 y

在下面的示例中,|| 运算符的右侧操作数是方法调用,如果左侧操作数的计算结果为 true,就不执行方法调用:

bool SecondOperand()
{
    Console.WriteLine("Second operand is evaluated.");
    return true;
}

bool a = true || SecondOperand();
Console.WriteLine(a);
// Output:
// True

bool b = false || SecondOperand();
Console.WriteLine(b);
// Output:
// Second operand is evaluated.
// True

逻辑 OR 运算符| 也计算操作数的逻辑 OR,但始终计算两个操作数。

可以为 null 的布尔逻辑运算符

对于 bool? 操作数,&(逻辑与)|(逻辑或)运算符支持三值逻辑,如下所示:

  • 仅当其两个操作数的计算结果都为 & 时,true 运算符才生成 true。 如果 xy 的计算结果为 false,则 x & y 将生成 false(即使另一个操作数的计算结果为 null)。 否则,x & y 的结果为 null

  • 仅当其两个操作数的计算结果都为 | 时,false 运算符才生成 false。 如果 xy 的计算结果为 true,则 x | y 将生成 true(即使另一个操作数的计算结果为 null)。 否则,x | y 的结果为 null

下表显示了该语义:

x y x & y x |y
Null Null
Null Null
Null Null
Null Null
Null Null Null Null

这些运算符的行为不同于值类型可以为 null 的典型运算符行为。 通常情况下,为值类型的操作数定义的运算符也能与值类型可以为 null 的相应操作数一起使用。 如果其任一操作数的计算结果为 null,此类运算符都会生成 null。 不过,即使操作数之一的计算结果为 &|null 运算符也可以生成非 null。 有关值类型可为空的运算符行为的详细信息,请参阅可为空的值类型一文的提升的运算符部分。

此外,你还可以将 !^ 运算符与 bool? 操作数结合使用,如下例所示:

bool? test = null;
Display(!test);         // output: null
Display(test ^ false);  // output: null
Display(test ^ null);   // output: null
Display(true ^ null);   // output: null

void Display(bool? b) => Console.WriteLine(b is null ? "null" : b.Value.ToString());

条件逻辑运算符 &&|| 不支持 bool? 操作数。

复合赋值

对于二元运算符 op,窗体的复合赋值表达式

x op= y

等效于

x = x op y

不过 x 只评估一次。

&|^ 运算符支持复合赋值,如下面的示例所示:

bool test = true;
test &= false;
Console.WriteLine(test);  // output: False

test |= true;
Console.WriteLine(test);  // output: True

test ^= false;
Console.WriteLine(test);  // output: True

注意

条件逻辑运算符 &&|| 不支持复合赋值。

运算符优先级

以下列表按优先级从高到低的顺序对逻辑运算符进行排序:

  • 逻辑非运算符 !
  • 逻辑与运算符 &
  • 逻辑异或运算符 ^
  • 逻辑或运算符 |
  • 条件逻辑与运算符 &&
  • 条件逻辑或运算符 ||

使用括号 () 可以更改运算符优先级决定的计算顺序:

Console.WriteLine(true | true & false);   // output: True
Console.WriteLine((true | true) & false); // output: False

bool Operand(string name, bool value)
{
    Console.WriteLine($"Operand {name} is evaluated.");
    return value;
}

var byDefaultPrecedence = Operand("A", true) || Operand("B", true) && Operand("C", false);
Console.WriteLine(byDefaultPrecedence);
// Output:
// Operand A is evaluated.
// True

var changedOrder = (Operand("A", true) || Operand("B", true)) && Operand("C", false);
Console.WriteLine(changedOrder);
// Output:
// Operand A is evaluated.
// Operand C is evaluated.
// False

要了解按优先级排序的完整 C# 运算符列表,请参阅 C# 运算符一文中的运算符优先级部分。

运算符可重载性

用户定义类型可以重载!&|^ 运算符。 重载二元运算符时,对应的复合赋值运算符也会隐式重载。 从 C# 14 开始,用户定义的类型可以显式重载复合赋值运算符,以提供更高效的实现。 通常,类型重载这些运算符,因为能够在原地更新值,而无需分配新增实例来保存二元运算结果。 如果类型不提供显式重载,编译器将生成隐式重载。

用户定义类型无法重载条件逻辑运算符 &&||。 不过,如果用户定义类型以某种方式重载 true 和 false 运算符以及 &| 运算符,可以对相应类型的操作数执行 &&|| 运算。 有关详细信息,请参阅 C# 语言规范用户定义条件逻辑运算符部分。

C# 语言规范

有关更多信息,请参阅 C# 语言规范的以下部分:

另请参阅