C# 运算符和表达式(C# 参考)

C# 提供了许多运算符。 其中许多都受到内置类型的支持,可用于对这些类型的值执行基本操作。 这些运算符包括以下组:

通常可以重载这些运算符,也就是说,可以为用户定义类型的操作数指定运算符行为。

最简单的 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.yf(x)a[i]x?.yx?[y]x++x--x!newtypeofcheckeduncheckeddefaultnameofdelegatesizeofstackallocx->y 主要
+x-xx~x++x--x^x(T)xawait、&&x*xtrue 和 false 一元
x..y 范围
switchwith switchwith 表达式
x * yx / yx % y 乘法
x + yx – y 加法
x << yx >> y Shift
x < yx > yx <= yx >= yisas 关系和类型测试
x == yx != y 相等
x & y 布尔逻辑 AND按位逻辑 AND
x ^ y 布尔逻辑 XOR按位逻辑 XOR
x | y 布尔逻辑 OR按位逻辑 OR
x && y 条件“与”
x || y 条件“或”
x ?? y Null 合并运算符
c ? t : f 条件运算符
x = yx += yx -= yx *= yx /= yx %= yx &= yx |= yx ^= yx <<= yx >>= yx ??= 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# 语言规范的以下部分:

请参阅