差别
这里会显示出您选择的修订版和当前版本之间的差别。
| 两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
| csharp:运算符 [2025/11/19 16:55] – [2. `??` 运算符 (双问号)] 张叶安 | csharp:运算符 [2025/12/22 11:37] (当前版本) – 张叶安 | ||
|---|---|---|---|
| 行 1: | 行 1: | ||
| - | 在 C# 中,`?` 和 `??` 运算符主要用于处理 **null 值(空值)** 以及 **条件逻辑**。它们不仅能简化代码,还能显著提高代码的可读性和安全性(防止空引用异常)。 | + | ====== |
| - | 以下是这两个符号在不同场景下的详细含义和用法: | + | C# 提供了丰富的运算符来处理算术、逻辑、位运算以及对象类型操作。除了处理 Null 值的 `?` 和 `??`,以下是其他核心运算符的详细分类讲解。 |
| - | --- | + | ===== 1. 算术运算符 (Arithmetic Operators) ===== |
| - | ### 1. ?运算符 (单问号) | + | |
| - | `?` 在 C# 中有三种主要的用法: | + | 用于执行基本的数学运算。 |
| - | #### A. 可空类型修饰符 (Nullable Type Modifier) | + | ^ 运算符 ^ 描述 ^ 示例 ^ |
| - | 用于定义一个**值类型**(如 | + | | `+` | 加法 (也用于字符串拼接) | `x + y` 或 `" |
| + | | `-` | 减法 | `x - y` | | ||
| + | | `*` | 乘法 | `x * y` | | ||
| + | | `/` | 除法 (整数相除会截断小数) | `10 / 3` 结果为 | ||
| + | | `%` | 取模 (求余数) | `10 % 3` 结果为 `1` | | ||
| + | | `++` | 自增 (前缀或后缀) | `x++` (先用后加) / `++x` (先加后用) | | ||
| + | | `--` | 自减 (前缀或后缀) | `x--` / `--x` | | ||
| - | | + | <code csharp> |
| - | * | + | int a = 10; |
| + | int b = 3; | ||
| + | Console.WriteLine(a / b); // 输出 3 (整数除法) | ||
| + | Console.WriteLine(a % b); // 输出 1 (余数) | ||
| + | Console.WriteLine(a + " is number" | ||
| + | </ | ||
| - | ```csharp | + | ===== 2. 逻辑运算符 (Logical Operators) ===== |
| - | int a = 10; // 正常 int,不能赋值 null | + | |
| - | int? b = null; // 可空 int,可以赋值 null | + | |
| - | ``` | + | |
| - | #### B. 三元条件运算符 | + | 主要用于布尔 |
| - | 这是 | + | |
| - | * | + | |
| - | * | + | |
| - | ```csharp | + | ^ 运算符 ^ 名称 ^ 描述 ^ |
| - | int x = 10; | + | | `&&` | 逻辑与 |
| - | string result = (x > 5) ? " | + | | `||` | 逻辑或 (OR) | 只要有一边为真,结果就为真。**短路特性**:如果左边为真,右边不再执行。 | |
| - | ``` | + | | `!` | 逻辑非 (NOT) | 取反,真变假,假变真。 | |
| - | #### C. Null 条件运算符 (Null-conditional Operator) - C# 6.0+ | + | <code csharp> |
| - | 也称为“安全导航运算符”。用于在访问成员(属性、方法)或索引器之前检查对象是否为 `null`。 | + | bool hasLogin = true; |
| - | * | + | bool hasPermission = false; |
| - | * | + | |
| - | ```csharp | + | if (hasLogin && !hasPermission) |
| - | string text = null; | + | { |
| - | int? length = text?.Length; // length 将会是 null,而不是抛出异常 | + | |
| - | ``` | + | } |
| + | </code> | ||
| - | --- | + | ===== 3. 比较/ |
| - | ### 2. ?? 运算符 (双问号) | + | |
| - | `??` 主要用于提供默认值。 | + | 用于比较两个值,返回 `true` 或 `false`。 |
| - | #### A. Null 合并运算符 | + | ^ 运算符 |
| - | 用于判断左侧的操作数是否为 | + | | `==` | 等于 | |
| - | * | + | | `!=` | 不等于 | |
| - | * | + | | `>` | 大于 | |
| + | | `<` | 小于 | | ||
| + | | `>=` | 大于等于 | | ||
| + | | `<=` | 小于等于 | | ||
| - | ```csharp | + | ===== 4. 类型检查与转换运算符 (Type Testing & Casting) ===== |
| - | string input = null; | + | |
| - | // 如果 input 是 null,则 name 变成 " | + | |
| - | string name = input ?? " | + | |
| - | ``` | + | |
| - | #### B. Null 合并赋值运算符 (Null-coalescing Assignment Operator) - C# 8.0+ | + | 在处理多态、接口或不确定类型的对象时非常重要。 |
| - | 这是 `??` 和 `=` 的组合。 | + | |
| - | * | + | |
| - | * | + | |
| - | ```csharp | + | ==== 4.1 is 运算符 ==== |
| - | List< | + | 用于检查对象是否兼容于指定类型。C# |
| - | numbers ??= new List< | + | |
| - | numbers ??= new List< | + | |
| - | ``` | + | |
| - | --- | + | <code csharp> |
| + | object obj = "Hello World"; | ||
| - | ### 综合代码示例 | + | // 传统用法 |
| + | if (obj is string) | ||
| + | { | ||
| + | Console.WriteLine(" | ||
| + | } | ||
| - | 为了更清晰地展示这些运算符的配合使用,请看下面的完整示例代码: | + | // 模式匹配用法 (推荐) |
| + | if (obj is string str) | ||
| + | { | ||
| + | // 如果转换成功,str 变量直接可用 | ||
| + | Console.WriteLine($" | ||
| + | } | ||
| + | </ | ||
| - | ```csharp | + | ==== 4.2 as 运算符 ==== |
| - | using System; | + | 用于显式引用转换。如果转换失败,返回 |
| - | using System.Collections.Generic; | + | |
| - | public class Program | + | <code csharp> |
| - | { | + | object obj = " |
| - | | + | string s = obj as string; // 转换成功 |
| - | { | + | System.IO.Stream stream |
| - | // 1. 可空类型修饰符 (?) | + | |
| - | // int? 表示这个变量可以存储数字,也可以存储 null | + | |
| - | int? nullableInt | + | |
| - | + | ||
| - | | + | |
| - | // 如果 nullableInt 是 null,则使用默认值 0 | + | |
| - | int finalValue | + | |
| - | Console.WriteLine($" | + | |
| - | // 3. 三元运算符 | + | if (stream != null) { /*...*/ } |
| - | | + | </code> |
| - | string status = (finalValue > 5) ? " | + | |
| - | Console.WriteLine($" | + | |
| - | // 4. Null 条件运算符 | + | ==== 4.3 typeof |
| - | Person person | + | 用于获取类型的 `System.Type` 对象(通常用于反射)。 |
| - | // 如果 person 为 null,name 直接为 null,不会报错 | + | |
| - | string name = person? | + | |
| - | | + | |
| - | // 组合使用:安全访问 + 默认值 | + | <code csharp> |
| - | // 如果 person 为 null 或者 Name 为 null,则显示 " | + | Type t = typeof(string); |
| - | | + | Console.WriteLine(t.FullName); // System.String |
| - | Console.WriteLine($"4. 组合使用结果: | + | </ |
| - | // 5. Null 合并赋值运算符 (??=) | + | ===== 5. 位运算符 (Bitwise Operators) ===== |
| - | List< | + | |
| - | + | ||
| - | // 因为 tags 是 null,所以进行赋值 | + | |
| - | tags ??= new List< | + | |
| - | tags.Add(" | + | |
| - | + | ||
| - | // 因为 tags 已经不是 null 了,所以右边不执行 | + | |
| - | tags ??= new List< | + | |
| - | + | ||
| - | Console.WriteLine($" | + | |
| - | } | + | |
| - | } | + | |
| - | // 定义一个简单的类用于测试 | + | 用于直接操作整数的二进制位。 |
| - | public class Person | + | |
| - | { | + | ^ 运算符 ^ 描述 ^ 示例 (假设 A=60, B=13) ^ |
| - | | + | | `&` | 按位与 | `A & B` (对应位都为1则为1) | |
| - | } | + | | `|` | 按位或 | `A | B` (对应位有一个为1则为1) | |
| - | ``` | + | | `^` | 按位异或 | `A ^ B` (对应位不同则为1) | |
| - | ### 总结表 | + | | `~` | 按位取反 | `~A` (0变1,1变0) | |
| + | | `<<` | 左移 | `A << 2` (左移2位,相当于乘以4) | | ||
| + | | `>>` | 右移 | `A >> 2` (右移2位,相当于除以4) | | ||
| + | |||
| + | ===== 6. Lambda 运算符 (=>) ===== | ||
| + | |||
| + | 读作 "goes to"。用于定义 Lambda 表达式(匿名函数)。 | ||
| + | |||
| + | <code csharp> | ||
| + | // 参数 => 表达式 | ||
| + | Func< | ||
| + | Console.WriteLine(square(5)); // 25 | ||
| + | |||
| + | // 在 LINQ 中广泛使用 | ||
| + | var list = new List< | ||
| + | var evens = list.Where(n => n % 2 == 0); | ||
| + | </ | ||
| + | |||
| + | ===== 7. 索引与范围运算符 (Index & Range) ===== | ||
| + | |||
| + | //(C# 8.0+)// 用于简化数组或集合的切片操作。 | ||
| + | |||
| + | ^ 运算符 ^ 名称 ^ 描述 ^ | ||
| + | | `^` | 索引运算符 | 从末尾开始计数。`^1` 是最后一个元素。 | | ||
| + | | `..` | 范围运算符 | 定义一个范围。`start..end` (包含 start,不包含 end)。 | | ||
| + | |||
| + | <code csharp> | ||
| + | var words = new string[] { " | ||
| + | |||
| + | // 获取最后一个元素 | ||
| + | string last = words[^1]; // " | ||
| + | |||
| + | // 获取中间两个元素 (索引1到索引3,不含3) | ||
| + | string[] middle = words[1..3]; | ||
| + | |||
| + | // 获取最后两个 | ||
| + | string[] lastTwo = words[^2..]; | ||
| + | </ | ||
| + | |||
| + | |||
| + | ===== 9. 综合总结表 | ||
| - | | 运算符 | 名称 | + | ^ 类别 ^ 常用运算符 |
| - | | **`?`** | 可空类型 | + | | **算术** |
| - | | **`?:`** | 三元运算符 | + | | **逻辑** | `&& |
| - | | **`?.`** | Null 条件 | + | | **比较** | `==`, `!=`, `>`, `<`, `>=`, `<=` | 结果总是 bool 类型。 | |
| - | | **`??`** | Null 合并 | + | | **位运算** | `&`, `|`, `^`, `~`, `<<`, `>>` | 用于底层二进制操作。 | |
| - | | **`??=`** | Null 合并赋值 | + | | **赋值** | `=`, `+=`, `-=`, `*=`, `/=` | `x += 5` 等同于 `x = x + 5`。 | |
| + | | **类型** | ||
| + | | **Lambda** | `=>` | 连接参数和方法体,用于 LINQ 和委托。 | | ||
| + | | **索引/ | ||
| + | | **Null处理**| `?`, `??`, `?.`, `??=` | 参见之前的 Null 运算符文档。 | | ||