【C#学习】运算符

C# 提供了许多运算符,这些运算符是指定要在表达式中执行哪些操作(数学、索引、函数调用等等)的符号。 可以重载许多应用于用户定义类型的运算符,从而更改其含义。

对整数类型执行的运算(如 ==!=<>&|)通常也可对枚举 (enum) 类型执行。

以下章节按最高优先级到最低优先级的顺序列示 C# 运算符。 各章节内运算符的优先级相同。

主要运算符

以下是具有最高优先级的运算符。 请注意,你可以单击运算符转到包含示例的详细页面。

x.y:成员访问。

x?.y:null 条件成员访问。 如果左操作数为 null,则返回 null

x?[y]:null 条件索引访问。 如果左操作数为 null,则返回 null

f(x):函数调用。

a[x]:聚合对象索引。

x++:后缀递增。 先返回 x 值,然后用加 1(通常加整数 1)后的 x 值更新存储位置。

x--:后缀递减。 先返回 x 值,然后用减 1(通常减整数 1)后的 x 值更新存储位置。

new:类型实例化。

typeof:返回表示操作数的 System.Type 对象。

checked:对整数运算启用溢出检查。

unchecked:对整数运算禁用溢出检查。 这是默认的编译器行为。

default(T):返回类型 T 的默认初始值,引用类型的默认初始值为 null,数值类型的默认初始值为 0,结构类型成员的默认初始填充值为 0/null

delegate:声明并返回委托实例。

sizeof:返回类型操作数的大小(以字节为单位)。

->:指针取消引用与成员访问相结合。

一元运算符

这些运算符的优先级比下一章节高,比上一章节低。 请注意,你可以单击运算符转到包含示例的详细页面。

+x:返回 x 的值。

-x:数值取反。

!x:逻辑取反。

~x:按位求补。

++x:前缀递增。 先用加 1(通常加整数 1)后的 x 值更新存储位置,然后返回 x 值。

--x:前缀递减。 先用减 1(通常减整数 1)后的 x 值更新存储位置,然后返回 x 值。

(T)x:类型显式转换。

await:等待 Task

&x:地址。

*x:取消引用。

乘法运算符

这些运算符的优先级比下一章节高,比上一章节低。 请注意,你可以单击运算符转到包含示例的详细页面。

x * y:乘法。

x / y:除法。 如果操作数均为整数,则结果为整数,舍去小数(例如,-7 / 2 is -3)。

x % y:取模。 如果操作数均为整数,则返回 x 除以 y 后的余数。 如果 q = x / y 且 r = x % y,则 x = q * y + r

相加运算符

这些运算符的优先级比下一章节高,比上一章节低。 请注意,你可以单击运算符转到包含示例的详细页面。

x + y:加法。

x:y:减法。

移位运算符

这些运算符的优先级比下一章节高,比上一章节低。 请注意,你可以单击运算符转到包含示例的详细页面。

x << y:左移位,右侧用 0 填充。

x >> y:右移位。 如果左操作数是 int 或 long,则左位数补符号位。 如果左操作数是 uint 或 ulong,则左位数补零。

关系和类型测试运算符

这些运算符的优先级比下一章节高,比上一章节低。 请注意,你可以单击运算符转到包含示例的详细页面。

x < y:小于(如果 x 小于 y,则为 true)。

x > y:大于(如果 x 大于 y,则为 true)。

x <= y:小于或等于。

x >= y:大于或等于。

is:类型兼容性。 如果求值后的左操作数可以转换为右操作数中指定的类型(静态类型),则返回 true。

as:类型转换。 返回左操作数并转换为右操作数中指定的类型(静态类型),但 as 返回 null,其中 (T)x 会引发异常。

相等运算符

这些运算符的优先级比下一章节高,比上一章节低。 请注意,你可以单击运算符转到包含示例的详细页面。

x == y:相等。 默认情况下,对于 string 以外的引用类型,此运算符返回引用相等(标识测试)。 但是,类型可以重载 ==,因此,如果你想测试标识,最好对 object 使用 ReferenceEquals 方法。

x != y:不相等。 请参阅有关 == 的注释。 如果某个类型重载 ==,则它必须重载 !=

逻辑 AND 运算符

此运算符的优先级比下一章节高,比上一章节低。 请注意,你可以单击该运算符转到包含示例的详细页面。

x & y:逻辑或位 AND。 与整数类型一起使用,并且通常允许 enum 类型。

逻辑 XOR 运算符

此运算符的优先级比下一章节高,比上一章节低。 请注意,你可以单击该运算符转到包含示例的详细页面。

x ^ y:逻辑或位 XOR。 通常可以将此运算符与整数类型和 enum 类型一起使用。

逻辑 OR 运算符

此运算符的优先级比下一章节高,比上一章节低。 请注意,你可以单击该运算符转到包含示例的详细页面。

x | y:逻辑或位 OR。 与整数类型一起使用,并且通常允许 enum 类型。

条件 AND 运算符

此运算符的优先级比下一章节高,比上一章节低。 请注意,你可以单击该运算符转到包含示例的详细页面。

x && y:逻辑 AND。 如果第一个操作数为 false,则 C# 不对第二个操作数求值。

条件 OR 运算符

此运算符的优先级比下一章节高,比上一章节低。 请注意,你可以单击该运算符转到包含示例的详细页面。

x || y:逻辑 OR。 如果第一个操作数为 true,则 C# 不对第二个操作数求值。

Null 合并运算符

此运算符的优先级比下一章节高,比上一章节低。 请注意,你可以单击该运算符转到包含示例的详细页面。

x ?? y:如果不为 null,则返回 x;否则返回 y

条件运算符

此运算符的优先级比下一章节高,比上一章节低。 请注意,你可以单击该运算符转到包含示例的详细页面。

t ? x : y:如果测试 t 为 true,则计算并返回 x;否则,计算并返回 y

赋值和 Lambda 运算符

这些运算符的优先级比下一章节高,比上一章节低。 请注意,你可以单击运算符转到包含示例的详细页面。

x = y:赋值。

x += y:递增。 x 值加 y 值,结果存储在 x 中,并返回新值。 如果 x 指定 event,则 y 必须是 C# 作为事件处理程序添加的相应函数。

x -= y:递减。 x 值减 y 值,结果存储在 x 中,并返回新值。 如果 x 指定 event,则 y 必须是 C# 作为事件处理程序删除的相应函数

x *= y:乘法赋值。 x 值乘以 y 值,结果存储在 x 中,并返回新值。

x /= y:除法赋值。 x 值除以 y 值,结果存储在 x 中,并返回新值。

x %= y:取模赋值。 x 值除以 y 值,余数存储在 x 中,并返回新值。

x &= y:AND 赋值。 y 值和 x 值相与,结果存储在 x 中,并返回新值。

x |= y:OR 赋值。 y 值和 x 值相或,结果存储在 x 中,并返回新值。

x ^= y:XOR 赋值。 y 值和 x 值相异或,结果存储在 x 中,并返回新值。

x <<= y:左移赋值。 将 x 值向左移动 y 位,结果存储在 x 中,并返回新值。

x >>= y:右移赋值。 将 x 值向右移动 y 位,结果存储在 x 中,并返回新值。

=>:lambda 声明。

算术溢出

算术运算符(+-*/)的计算结果可能会超出所涉数值类型的可取值范围。 详细信息应参考特定运算符的相关章节,而一般情况下:

  • 整数算术溢出或者引发 OverflowException,或者放弃结果的最高有效位。 整数被零除总是引发 @System.DivideByZeroException。

    发生整数溢出时,具体影响视执行上下文而定,上下文可为 checked 或 unchecked。 在 checked 上下文中引发 OverflowException。 在 unchecked 上下文中,放弃结果的最高有效位并继续执行。 因此,C# 让你有机会选择处理或忽略溢出。 默认情况下,算术运算发生在 unchecked 上下文中。

    除算术运算以外,整型类型之间的显式转换也会导致溢出(例如,将 long 显式转换成 int),并受到 checked 或 unchecked 执行的约束。 但是,位运算符和移位运算符永远不会导致溢出。

  • 浮点算术溢出或被零除从不引发异常,因为浮点类型基于 IEEE 754,因此可以表示无穷大和 NaN(非数值)。

  • 小数算术溢出总是引发 OverflowException。 小数被零除总是引发 DivideByZeroException

<think>好的,用户想了解C#中的关系运算符使用指南。首先,我需要回顾一下C#中的关系运算符有哪些,包括它们的语法和用法。C#中的关系运算符主要有==、!=、<、>、<=和>=,这些用于比较两个值的大小或相等性,返回布尔值。 接下来,我需要整理每个运算符的具体作用和使用场景。例如,==用于判断两个操作数是否相等,而!=则相反。需要注意的是,对于引用类型,默认比较的是引用地址,而非对象内容,因此可能需要重载运算符来改变这一行为。 然后,用户可能对运算符重载感兴趣,特别是关系运算符的重载规则。根据引用[2],C#要求成对重载比较运算符,比如重载了==就必须重载!=,并且必须返回bool类型。这部分需要详细说明如何正确重载,避免编译错误。 还需要考虑到值类型和引用类型的差异。例如,string类已经重载了==,使其比较内容而不是引用,这可以作为例子来说明。同时,用户可能在实际编码中遇到自定义结构体或类的比较问题,这时运算符重载就显得尤为重要。 另外,应该提供一些代码示例,展示如何声明和使用重载的关系运算符。比如,定义一个自定义的Vector类,并重载==和!=,同时实现Equals方法和GetHashCode,以确保一致性和正确性。 用户可能还会关心运算符重载的注意事项,比如性能影响、逻辑一致性等。需要提醒用户在重载时保持逻辑与预期一致,避免混淆。例如,重载的==应与Equals方法行为一致,避免不一致的结果。 最后,根据用户提供的引用,尤其是引用[2]和[3],需要准确引用相关规则,如成对重载和返回bool类型的要求。同时,引用[4]提到提高代码可读性,这也是重载运算符的重要优势之一,可以结合这一点进行说明。 可能还需要生成相关问题,比如如何重载其他运算符,或者比较运算符在集合排序中的应用,这有助于用户进一步学习。同时,确保回答结构清晰,分点说明,帮助用户逐步理解。</think>### C# 关系运算符使用指南 C# 中的关系运算符用于比较两个操作数的大小或相等性,**返回值为布尔类型(`bool`)**,是条件判断和循环控制的核心工具。以下是具体运算符及其用法: --- #### 一、基础关系运算符 1. **等于 `==`** ```csharp int a = 5, b = 5; bool result = (a == b); // true ``` **注意**:引用类型默认比较对象地址(如类对象),但 `string` 类型已重载为值比较[^2]。 2. **不等于 `!=`** ```csharp string s1 = "hello", s2 = "world"; bool result = (s1 != s2); // true ``` 3. **小于 `<` 与大于 `>`** ```csharp double x = 3.14, y = 2.71; bool less = (y < x); // true bool greater = (y > x); // false ``` 4. **小于等于 `<=` 与大于等于 `>=`** ```csharp int score = 85; bool pass = (score >= 60); // true ``` --- #### 二、运算符重载规则 1. **必须成对重载** 若重载 `==`,则必须同时重载 `!=`,否则引发编译错误。 ```csharp public static bool operator ==(Vector v1, Vector v2) => v1.X == v2.X && v1.Y == v2.Y; public static bool operator !=(Vector v1, Vector v2) => !(v1 == v2); ``` 2. **必须返回 `bool` 类型** 比较运算符的返回值只能是 `true` 或 `false`,不同于算术运算符。 3. **与 `Equals` 方法的一致性** 建议同时重写 `Equals` 和 `GetHashCode` 方法以保证逻辑统一: ```csharp public override bool Equals(object obj) => obj is Vector v && this == v; public override int GetHashCode() => (X, Y).GetHashCode(); ``` --- #### 三、自定义类型示例 ```csharp public struct Vector { public int X { get; } public int Y { get; } public Vector(int x, int y) { X = x; Y = y; } // 重载关系运算符 public static bool operator ==(Vector v1, Vector v2) => v1.X == v2.X && v1.Y == v2.Y; public static bool operator !=(Vector v1, Vector v2) => !(v1 == v2); public static bool operator <(Vector v1, Vector v2) => v1.Magnitude() < v2.Magnitude(); public static bool operator >(Vector v1, Vector v2) => v1.Magnitude() > v2.Magnitude(); private double Magnitude() => Math.Sqrt(X * X + Y * Y); } // 使用示例 Vector v1 = new Vector(3, 4); Vector v2 = new Vector(1, 2); bool isEqual = (v1 == v2); // false bool isGreater = (v1 > v2); // true (5 > √5) ``` --- #### 四、注意事项 1. **避免空引用异常** 重载时需处理 `null` 值: ```csharp public static bool operator ==(MyClass a, MyClass b) { if (a is null) return b is null; return a.Equals(b); } ``` 2. **性能优化** 频繁调用的运算符(如集合排序中的 `<`)应保持高效计算。 3. **语义清晰性** 重载后的运算符行为需符合直觉(如 `>` 表示物理量的大小比较)[^4]。 --- §§ 相关问题 §§ 1. 如何重载 C# 中的算术运算符(如 `+`、`-`)? 2. 在自定义类型中,为什么需要同时重写 `Equals` 和 `GetHashCode`? 3. 关系运算符在 LINQ 查询中有哪些典型应用场景? [^1]: 基础运算符定义参考 : 运算符重载规则 : 运算符重载的实际意义
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值