C# 运算符和表达式(C# 参考)
C# 提供了许多运算符。 其中许多都受到内置类型的支持,可用于对这些类型的值执行基本操作。 这些运算符包括以下组:
- 算术运算符,将对数值操作数执行算术运算
- 比较运算符,将比较数值操作数
- 布尔逻辑运算符,将对
bool
操作数执行逻辑运算 - 位运算符和移位运算符,将对整数类型的操作数执行位运算或移位运算
- 相等运算符,将检查其操作数是否相等
通常可以重载这些运算符,也就是说,可以为用户定义类型的操作数指定运算符行为。
最简单的 C# 表达式是文本(例如整数和实数)和变量名称。 可以使用运算符将它们组合成复杂的表达式。 运算符优先级和结合性决定了表达式中操作的执行顺序。 可以使用括号更改由运算符优先级和结合性决定的计算顺序。
在下面的代码中,表达式的示例位于赋值的右侧:
int a, b, c;
a = 7;
b = a;
c = b++;
b = a + b * c;
c = a >= 100 ? b : c / 10;
a = (int)Math.Sqrt(b * b + c * c);
string s = "String literal";
char l = s[s.Length - 1];
var numbers = new List<int>(new[] { 1, 2, 3 });
b = numbers.FindLast(n => n > 1);
通常情况下,表达式会生成结果,并可包含在其他表达式中。 void
方法调用是不生成结果的表达式的示例。 它只能用作语句,如下面的示例所示:
Console.WriteLine("Hello, world!");
下面是 C# 提供的一些其他类型的表达式:
内插字符串表达式,提供创建格式化字符串的便利语法:
var r = 2.3; var message = $"The area of a circle with radius {r} is {Math.PI * r * r:F3}."; Console.WriteLine(message); // Output: // The area of a circle with radius 2.3 is 16.619.
Lambda 表达式,可用于创建匿名函数:
int[] numbers = { 2, 3, 4, 5 }; var maximumSquare = numbers.Max(x => x * x); Console.WriteLine(maximumSquare); // Output: // 25
查询表达式,可用于直接以 C# 使用查询功能:
var scores = new[] { 90, 97, 78, 68, 85 }; IEnumerable<int> highScoresQuery = from score in scores where score > 80 orderby score descending select score; Console.WriteLine(string.Join(" ", highScoresQuery)); // Output: // 97 90 85
可使用表达式主体定义为方法、构造函数、属性、索引器或终结器提供简洁的定义。
运算符优先级
在包含多个运算符的表达式中,先按优先级较高的运算符计算,再按优先级较低的运算符计算。 在下面的示例中,首先执行乘法,因为其优先级高于加法:
var a = 2 + 2 * 2;
Console.WriteLine(a); // output: 6
使用括号更改运算符优先级所施加的计算顺序:
var a = (2 + 2) * 2;
Console.WriteLine(a); // output: 8
下表按最高优先级到最低优先级的顺序列出 C# 运算符。 每行中运算符的优先级相同。
运算符 | 类别或名称 |
---|---|
x.y、f(x)、a[i]、x?.y 、x?[y] 、x++、x--、x!、new、typeof、checked、unchecked、default、nameof、delegate、sizeof、stackalloc、x->y |
主要 |
+x、-x、x、~x、++x、--x、^x、(T)x、await、&&x、*x、true 和 false | 一元 |
x..y | 范围 |
switch、with | switch 和 with 表达式 |
x * y、x / y、x % y | 乘法 |
x + y、x – y | 加法 |
x << y、x >> y | Shift |
x < y、x > y、x <= y、x >= y、is、as | 关系和类型测试 |
x == y、x != y | 相等 |
x & y |
布尔逻辑 AND 或按位逻辑 AND |
x ^ y |
布尔逻辑 XOR 或按位逻辑 XOR |
x | y |
布尔逻辑 OR 或按位逻辑 OR |
x && y | 条件“与” |
x || y | 条件“或” |
x ?? y | Null 合并运算符 |
c ? t : f | 条件运算符 |
x = y、x += y、x -= y、x *= y、x /= y、x %= y、x &= y、x |= y、x ^= y、x <<= y、x >>= y、x ??= y、=> | 赋值和 lambda 声明 |
运算符结合性
当运算符的优先级相同,运算符的结合性决定了运算的执行顺序:
- 左结合运算符按从左到右的顺序计算。 除赋值运算符和 null 合并运算符外,所有二元运算符都是左结合运算符。 例如,
a + b - c
将计算为(a + b) - c
。 - 右结合运算符按从右到左的顺序计算。 赋值运算符、null 合并运算符、lambda 和条件运算符
?:
是右结合运算符。 例如,x = y = z
将计算为x = (y = z)
。
使用括号更改运算符结合性所施加的计算顺序:
int a = 13 / 5 / 2;
int b = 13 / (5 / 2);
Console.WriteLine($"a = {a}, b = {b}"); // output: a = 1, b = 6
操作数计算
与运算符的优先级和结合性无关,从左到右计算表达式中的操作数。 以下示例展示了运算符和操作数的计算顺序:
表达式 | 计算顺序 |
---|---|
a + b |
a, b, + |
a + b * c |
a, b, c, *, + |
a / b + c * d |
a, b, /, c, d, *, + |
a / (b + c) * d |
a, b, c, +, /, d, * |
通常,会计算所有运算符操作数。 但是,某些运算符有条件地计算操作数。 也就是说,此类运算符的最左侧操作数的值定义了是否应计算其他操作数,或计算其他哪些操作数。 这些运算符有条件逻辑 AND (&&
) 和 OR (||
) 运算符、null 合并运算符 ??
和 ??=
、null 条件运算符 ?.
和 ?[]
以及条件运算符?:
。 有关详细信息,请参阅每个运算符的说明。
C# 语言规范
有关更多信息,请参阅 C# 语言规范的以下部分: