一.c# 初级

44 次查看
# 一.c# 基础阶段

## 1.程序结构

```c#
using System; // 引入命名空间

namespace HelloWorld // 命名空间声明
{
    class Program // 类声明
    {
        static void Main(string[] args) // Main方法,程序入口点
        {
            Console.WriteLine("Hello, World!"); // 语句
        }
    }
}
```

## 2.关键字

C# 关键字是语言中具有特殊含义的保留字,不能用作标识符(如变量名、类名等)
**1). 访问修饰符**

| 关键字             | 描述                         |
| ------------------ | ---------------------------- |
| public             | 访问不受限制                 |
| private            | 只能在当前类中访问           |
| protected          | 只能在当前类或派生类中访问   |
| internal           | 只能在当前程序集中访问       |
| protected internal | 在当前程序集或派生类中可访问 |
| private protected  | 在当前程序集的派生类中可访问 |
| file               | 仅在当前文件中可访问         |

**2). 类型定义**
|关键字 |描述|
|-|-|
|class| 定义类|
|struct| 定义结构|
|interface |定义接口|
|enum| 定义枚举|
|delegate |定义委托|
|record |定义记录类型(新特性)|

**3). 基本数据类型**
|关键字 |描述|
|-|-|
|bool |布尔值(true/false)|
|byte, sbyte| 8位整数|
|short, ushort |16位整数|
|int, uint |32位整数|
|long, ulong| 64位整数|
|float |32位浮点数|
|double |64位浮点数|
|decimal |128位十进制数|
|char| Unicode字符|
|string |字符串|
|object |所有类型的基类|
|dynamic| 动态类型|

**4).流程控制**
|关键字 |描述|
|-|-|
|if, else |条件语句|
|switch, case, default| 多分支选择|
|for, foreach |循环结构|
|while, do |循环结构|
|break |跳出循环或switch|
|continue |跳过当前循环迭代|
|goto |跳转到标签(不推荐)|
|return |从方法返回值|

**5).方法相关**
|关键字| 描述|
|-|-|
|void |表示方法不返回值|
|ref| 按引用传递参数|
|out| 输出参数|
|params |可变数量参数|
|async| 异步方法|
|await |等待异步操作完成|

**6).类成员修饰符**
|关键字| 描述|
|-|-|
|static |静态成员|
|const| 常量|
|readonly |只读字段|
|new |创建对象或隐藏基类成员|
|this |当前实例引用|
|base |基类访问|
|virtual| 可重写的方法|
|override |重写基类方法|
|abstract| 抽象类或方法|
|sealed |密封类或方法|
|partial |分部类/方法|

**7).异常处理**
|关键字| 描述|
|-|-|
|try |尝试执行代码块|
|catch| 捕获异常|
|finally |无论是否异常都会执行|
|throw| 抛出异常|

**8).命名空间和程序集**
|关键字 |描述|
|-|-|
|namespace |定义命名空间|
|using |引入命名空间或创建别名|

**9).泛型**

| 关键字  | 描述             |
| ------- | ---------------- |
| where   | 泛型类型约束     |
| default | 获取类型的默认值 |

**10).类型操作**
|关键字 |描述|
|-|-|
|is |类型检查|
|as |安全类型转换|
|sizeof |获取类型大小|
|typeof |获取类型信息|
|nameof |获取变量、类型或成员的名称|

**11).上下文关键字**

| 关键字      | 描述                         |
| ----------- | ---------------------------- |
| add, remove | 事件访问器                   |
| get, set    | 属性访问器                   |
| init        | 仅初始化属性设置器           |
| value       | 属性设置器中的隐式参数       |
| global      | 全局命名空间别名             |
| when        | catch或switch case的筛选条件 |
| with        | 用于记录类型的非破坏性修改   |

**12).不安全代码**
|关键字 |描述|
|-|-|
|unsafe |不安全代码块|
|fixed |固定指针|
|stackalloc |栈上分配内存|
|volatile |易变字段|

**13).运算符重载**
|关键字 |描述|
|-|-|
|operator |重载运算符|
|checked, unchecked |控制算术溢出检查|

**14).其他**

| 关键字 | 描述         |
| ------ | ------------ |
| var    | 隐式类型变量 |
| yield  | 迭代器生成   |

## 3.数据类型和转换

### 3.1 值类型

**整数类型**

| 类型         | 关键字 | 大小 | 取值范围/描述                   | 默认值 | 示例                |
| ------------ | ------ | ---- | ------------------------------- | ------ | ------------------- |
| 有符号字节   | sbyte  | 8位  | -128 到 127                     | 0      | sbyte a = -100;     |
| 无符号字节   | byte   | 8位  | 0 到 255                        | 0      | byte b = 200;       |
| 有符号短整型 | short  | 16位 | -32,768 到 32,767               |        | 0 short c = -20000; |
| 无符号短整型 | ushort | 16位 | 0 到 65,535                     | 0      | ushort d = 60000;   |
| 有符号整型   | int    | 32位 | -2,147,483,648 到 2,147,483,647 | 0      | int e = -1000000;   |
| 无符号整型   | uint   | 32位 | 0 到 4,294,967,295              | 0      | uint f = 4000000;   |
| 有符号长整型 | long   | 64位 | -9.2×10¹⁸ 到 9.2×10¹⁸           | 0L     | long g = -5L;       |
| 无符号长整型 | ulong  | 64位 | 0 到 1.8×10¹⁹                   | 0UL    | ulong h = 10UL;     |

**浮点类型**
|类型 |关键字 |大小 |精度/范围 |默认值 |示例|
|-|-|-|-|-|-|
|单精度浮点 |float |32位| 7位精度,±1.5×10⁻⁴⁵到±3.4×10³⁸| 0.0F| float i = 3.14F;|
|双精度浮点 |double |64位 |15-16位精度,±5.0 × 10⁻³²⁴ 到 ±1.7 × 10³⁰⁸| 0.0D |double j = 3.14159;|
|十进制数 |decimal |128位 |28-29位精度,±1.0 × 10⁻²⁸ 到 7.9 × 10²⁸ |0.0M |decimal k = 123.456M;|

**其他值类型**
|类型 |关键字 |大小 |描述 |默认值| 示例|
|-|-|-|-|-|-|
|布尔型 |bool |8位| true 或 false| false |bool m = true;|
|字符型 |char |16位 |Unicode字符 (U+0000到U+FFFF) |'\0' |char l = 'A';|

**复合值类型**

```c#
// 结构体示例
public struct Point
{
    public int X;
    public int Y;
}

// 枚举示例
public enum Color : byte  // 可指定基础类型
{
    Red = 1,
    Green = 2,
    Blue = 3
}

// 元组示例
var tuple = (1, "text");  // ValueTuple<int, string>
```

### 3.2 引用类型

内置引用类型
|类型 |关键字| 描述 |默认值 |示例|
|-|-|-|-|-|
|字符串 |string |Unicode字符序列 |null |string s = "Hello";|
|对象 |object |所有类型的基类| null |object o = new();|
|动态类型 |dynamic |运行时类型检查 |null |dynamic d = 10;|

复合引用类型

```c#
// 类示例
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

// 接口示例
public interface IDrawable
{
    void Draw();
}

// 数组示例
int[] numbers = { 1, 2, 3 };           // 一维数组
int[,] matrix = new int[2, 3];         // 二维数组
int[][] jagged = new int[3][];          // 交错数组

// 委托示例
public delegate void MyDelegate(string msg);
```

记录类型

```c#
// 记录类 (不可变引用类型)
public record Product(string Name, decimal Price);

// 记录结构 (不可变值类型)
public readonly record struct Point(int X, int Y);
```

### 3.3 特殊类型

可为空值类型

```c#
int? nullableInt = null;           // Nullable<int>
double? nullableDouble = 3.14;     // Nullable<double>
bool? nullableBool = null;         // Nullable<bool>

// 安全访问
int value = nullableInt ?? -1;     // 如果null则返回-1
```

指针类型

```c#
unsafe
{
    int value = 10;
    int* pointer = &value;          // 获取地址

    // 指针运算
    int* p = stackalloc int[10];   // 栈上分配
    p[0] = 1;

    // 固定托管对象
    int[] array = { 1, 2, 3 };
    fixed (int* ptr = array)
    {
        for (int i = 0; i < array.Length; i++)
        {
            Console.WriteLine(*(ptr + i));
        }
    }
}
```

其他特殊类型

| 类型/概念  | 描述             | 示例             |
| ---------- | ---------------- | ---------------- |
| void       | 表示无返回值     | void Method()    |
| var        | 隐式类型推断     | var x = 10;      |
| nint/nuint | 平台相关整数大小 | nint size = 100; |

### 3.4 类型转换

隐式转换 (自动)

```c#
int i = 10;
long l = i;     // 小范围转大范围
```

显式转换 (强制)

```c#
double d = 3.14;
int i = (int)d; // 大范围转小范围
```

方法转换

```c#
// Parse/TryParse
int num = int.Parse("123");
bool success = int.TryParse("abc", out int result);

// Convert类
decimal dec = Convert.ToDecimal(3.14);
```

类型检查与转换

```c#
object obj = "Hello";

// is 检查
if (obj is string) { /*...*/ }

// as 安全转换
string str = obj as string;
if (str != null) { /*...*/ }

// 模式匹配 (C# 7+)
if (obj is string s) { /* 使用s */ }
```

## 4.变量

**4.1 变量基础概念**

变量定义

- 变量是存储数据的命名内存位置
- 必须先声明后使用
- 包含:变量名、数据类型和值

变量声明语法

```c#
数据类型 变量名;          // 声明
数据类型 变量名 = 初始值;  // 声明并初始化
```

**4.2 变量类型分类**

按数据类型分类

| 类型         | 示例                 | 说明                       |
| ------------ | -------------------- | -------------------------- |
| 值类型变量   | int age = 25;        | 直接存储数据               |
| 引用类型变量 | string name = "Tom"; | 存储数据引用               |
| 指针类型变量 | int\* ptr;           | 存储内存地址(unsafe上下文) |

按作用域分类

| 类型     | 声明位置         | 生命周期           |
| -------- | ---------------- | ------------------ |
| 局部变量 | 方法/代码块内    | 所在代码块执行期间 |
| 字段变量 | 类/结构体内      | 所属对象存在期间   |
| 静态变量 | 类中用static声明 | 程序运行期间       |
| 参数变量 | 方法参数列表     | 方法执行期间       |

**4.3 变量/常量声明**

基本变量声明

```c#
int count;                  // 声明未初始化
double price = 19.99;        // 声明并初始化
char grade = 'A';           // 字符类型
bool isCompleted = false;   // 布尔类型
```

类型推断(var)

```c#
var message = "Hello";      // 编译为string
var number = 42;            // 编译为int
var list = new List<int>();  // 编译为List<int>

// var必须初始化,不能用于字段声明
// var不能用于方法参数和返回类型
```

常量声明

```c#
const double PI = 3.14159;
const int MaxUsers = 100;

// 常量必须在声明时初始化
// 常量默认为静态(static)
```

元组变量

```c#
// 命名元组
var person = (Name: "Alice", Age: 25);
Console.WriteLine(person.Name);

// 解构元组
(string name, int age) = person;
```

**4.4 变量作用域规则**

局部变量作用域

```c#
void Method()
{
    int x = 10;  // 作用域开始

    if (true)
    {
        int y = 20;  // 仅在此块内有效
        x = 30;      // 可以访问外部变量
    }

    // y = 40;  // 错误!y不可访问
}  // 作用域结束,x被销毁
```

字段变量作用域

```c#
class MyClass
{
    private int _field;  // 类级作用域

    void Method()
    {
        _field = 10;     // 可在类内任何方法访问
    }
}
```

变量隐藏

```c#
int x = 10;

if (true)
{
    int x = 20;  // 隐藏外部x
    Console.WriteLine(x);  // 20
}

Console.WriteLine(x);  // 10
```

**4.5 特殊变量类型**

可为空变量

```c#
int? nullableInt = null;   // Nullable<int>
double? price = null;

// 安全访问
int value = nullableInt ?? -1;  // null合并运算符
```

固定大小缓冲区

```c#
unsafe struct FixedBuffer
{
    public fixed char buffer[128];  // 固定大小数组
}
```

范围变量

> 范围变量(Range Variable)是LINQ查询表达式中的特殊变量,它表示数据源中的单个元素。范围变量是LINQ查询中的"临时代表",代表数据集合中的单个元素,只在当前查询表达式中有效,类似于foreach循环中的迭代变量。

```c#
var query = from num in numbers
            where num > 5
            select num;  // num是范围变量
```

**4.6 变量命名规范**

1. 常规变量​​:camelCase (totalCount, userName)
2. ​​私有字段​​:\_camelCase (\_instanceCount, \_isInitialized)
3. ​​常量​​:PascalCase (MAX_SIZE, DEFAULT_TIMEOUT)
4. ​​布尔变量​​:以is/can/has开头 (isActive, hasPermission)

## 5.运算符和表达式

### 5.1 运算符

算术运算符
|运算符| 描述 |示例 |结果|
|-|-|-|-|
|+ |加法 |5 + 3| 8|
|- |减法| 10 - 4| 6|
|_| 乘法 |3 _ 4| 12|
|/ |除法| 10 / 3 |3|
|% |取模 |10 % 3 |1|
|++ |自增 |a++| a+1|
|-- |自减| a--| a-1|

关系运算符
|运算符| 描述| 示例 |结果|
|-|-|-|-|
|== |等于 |5 == 5 |true|
|!= |不等于| 5 != 3 |true|
|> |大于 |5 > 3| true|
|< |小于 |5 < 3 |false|
|>= |大于等于 |5 >= 5| true|
|<= |小于等于| 5 <= 3 |false|

逻辑运算符
![](https://www.diandiandidi.club:12346/api/note/getImage/19/ad938294-90dc-45b9-8f5a-58be7b03fb41-.png)
位运算符
![](https://www.diandiandidi.club:12346/api/note/getImage/19/67a6c2fb-c262-424b-b93a-f299e54836f2-.png)

赋值运算符
|运算符 |示例 |等价形式|
|-|-|-|
|= |a = 5 | |
|+= |a += 3 |a = a + 3|
|-= |a -= 2 |a = a - 2|
| \* = |a \*= 4 |a = a \* 4|
|/= |a /= 2| a = a / 2|
|%= |a %= 3 |a = a % 3|

特殊运算符
|运算符| 描述 |示例|
|-|-|-
|?: |三元条件运算符 |x > 0 ? 1 : -1|
|?? |null合并运算符| name ?? "匿名"|
|?. |null条件运算符 |person?.Name|
|is |类型检查 |obj is string|
|as |安全类型转换 |obj as string|
|sizeof |获取类型大小| sizeof(int)|
|typeof |获取类型对象 |typeof(string)|

### 5.2 表达式

基本表达式

```c#
42                  // 字面量表达式
a                   // 变量表达式
a + b               // 算术表达式
a > b               // 关系表达式
```

复合表达式

```c#
(a + b) * c         // 组合算术表达式
(a > b) && (c < d)  // 组合逻辑表达式
```

Lambda表达式

```c#
x => x * x          // 单参数Lambda
() => Console.WriteLine("Hello") // 无参数Lambda
```

查询表达式

```c#
from n in numbers
where n > 5
select n           // LINQ查询表达式
```

### 5.3 运算符优先级

(从高到低)1.成员访问 .、方法调用 ()、数组索引 [] 2.一元运算符 +、-、!、~、++、--、(类型) 3.乘除 \*、/、% 4.加减 +、- 5.移位 <<、>> 6.关系 <、>、<=、>=、is、as 7.相等 ==、!= 8.位与 & 9.位异或 ^ 10.位或 | 11.逻辑与 && 12.逻辑或 ||
13.null合并 ?? 14.三元条件 ?: 15.赋值 =、+=、-= 等

### 5.4 实用技巧

1.用括号明确优先级​​:(a + b) _ c 比 a + b _ c 更清晰

2.​​null检查简化​​:

```c#
// 传统方式
if (obj != null) { var name = obj.Name; }

// 使用?.运算符
var name = obj?.Name;
```

3.类型转换最佳实践:

```c#
// 安全转换(推荐)
string s = obj as string;
if (s != null) { ... }

// 强制转换(确定类型时使用)
string s = (string)obj;
```

4.​​模式匹配(C# 7.0+)​​:

```c#
if (obj is string str) {
    Console.WriteLine(str.Length);
}
```

5.范围运算符(C# 8.0+)​​:

```c#
int[] arr = {1, 2, 3, 4, 5};
var sub = arr[1..4];  // 获取索引1-3 [2,3,4]
```

### 5.5 注意事项

1.整数除法会截断小数部分:5 / 2 = 2
2.++a(前缀)和 a++(后缀)有区别:

```c#
int a = 1;
int b = a++; // b=1, a=2
int c = ++a; // c=3, a=3
```

3.浮点数比较应使用容差而非直接==:

```c#
// 不推荐
if (d1 == d2) {...}

// 推荐
if (Math.Abs(d1 - d2) < 0.0001) {...}
```

4.运算符重载示例:

```c#
public class Program
{
    public static void Main(string[] args)
    {
        Vector2D v1 = new Vector2D(1, 2);
        Vector2D v2 = new Vector2D(3, 4);
        var n = (v1 + v2);
        Console.WriteLine($"new x:{n.X},new y:{n.Y}");
    }
}
public class Vector2D
{
    public double X { get; set; }
    public double Y { get; set; }
    public Vector2D(double x, double y)
    {
        X = x;
        Y = y;
    }
    public static Vector2D operator +(Vector2D a, Vector2D b)
    {
        return new Vector2D(a.X + b.X, a.Y + b.Y);
    }
    public static Vector2D operator -(Vector2D a, Vector2D b)
    {
        return new Vector2D(a.X - b.X, a.Y - b.Y);
    }
}
```

## 6.控制结构

### 6.1 条件控制结构

if

```c#
if (条件表达式)
{
    // 条件为真时执行的代码
}

if (条件表达式)
{
    // 条件为真时执行
}
else
{
    // 条件为假时执行
}

if (条件1)
{
    // 条件1为真时执行
}
else if (条件2)
{
    // 条件2为真时执行
}
else
{
    // 所有条件为假时执行
}
```

switch

```c#
switch (表达式)
{
    case 值1:
        // 代码块1
        break;
    case 值2:
        // 代码块2
        break;
    default:
        // 默认代码块
        break;
}


// 7.0+ 增强特性​​
switch (shape)
{
    case Circle c:
        Console.WriteLine($"圆形,半径={c.Radius}");
        break;
    case Rectangle r when r.Width == r.Height:
        Console.WriteLine($"正方形,边长={r.Width}");
        break;
    case null:
        throw new ArgumentNullException(nameof(shape));
    default:
        Console.WriteLine("未知形状");
        break;
}
```

### 6.2 循环控制

for

```c#
for (初始化; 条件; 迭代)
{
    // 循环体
}

// 示例
for (int i = 0; i < 10; i++)
{
    Console.WriteLine(i);
}
```

while

```c#
while (条件表达式)
{
    // 循环体
}

// 示例
int i = 0;
while (i < 10)
{
    Console.WriteLine(i);
    i++;
}
```

do-while

```c#
do
{
    // 循环体(至少执行一次)
} while (条件表达式);

// 示例​​
int i = 0;
do
{
    Console.WriteLine(i);
    i++;
} while (i < 10);
```

foreach

```c#
foreach (类型 变量 in 集合)
{
    // 循环体
}

// 示例
string[] names = { "Alice", "Bob", "Charlie" };
foreach (string name in names)
{
    Console.WriteLine(name);
}
```

### 6.3 跳转语句

**break**

立即终止当前循环或switch语句

```c#
for (int i = 0; i < 10; i++)
{
    if (i == 5)
        break; // 当i=5时退出循环
    Console.WriteLine(i);
}
```

**continue**
跳过当前循环迭代,继续下一次迭代

```c#
for (int i = 0; i < 10; i++)
{
    if (i % 2 == 0)
        continue; // 跳过偶数
    Console.WriteLine(i);
}
```

**return**
立即退出当前方法,并可返回一个值

```c#
int Add(int a, int b)
{
    return a + b; // 返回计算结果
}
```

**goto**

```c#
for (int i = 0; i < 10; i++)
{
    if (i == 5)
        goto EndLoop; // 跳转到标签处
    Console.WriteLine(i);
}
EndLoop:
Console.WriteLine("循环结束");
```

### 6.4 特殊控制结构

try-catch-finally

```c#
try
{
    // 可能抛出异常的代码
}
catch (特定异常类型 ex)
{
    // 处理特定异常
}
catch (Exception ex)
{
    // 处理所有其他异常
}
finally
{
    // 无论是否发生异常都会执行的代码
}
```

using

```c#
using (var resource = new DisposableResource())
{
    // 使用资源
    // 离开作用域时自动调用Dispose(),在处理IO流相关操作时用到
    }
```

yield return

```c#
IEnumerable<int> GetNumbers()
{
    for (int i = 0; i < 10; i++)
    {
        yield return i; // 延迟生成值
    }
}
```

### 6.5 C# 8.0+ 新特性

switch

```c#
var result = operation switch
{
    "+" => a + b,
    "-" => a - b,
    "*" => a * b,
    "/" => a / b,
    _ => throw new InvalidOperationException("未知运算符")
};
```

模式匹配增强

```c#
if (obj is string { Length: >5 } s)
{
    Console.WriteLine($"长字符串: {s}");
}
```

异步流

```c#
await foreach (var item in GetAsyncItems())
{
    Console.WriteLine(item);
}
```

## 7.数组

### 7.1 数组基础概念

7.1.1 数组核心特性

- 固定大小​​:创建后长度不可变
- 类型统一​​:所有元素必须是相同类型
- 连续内存​​:元素在内存中顺序存储
- ​​索引访问​​:通过下标访问元素(从0开始)
- ​​性能优势​​:访问速度快(O(1)),缓存友好

7.1.2 数组分类

- 一维数组:int[]
- 多维数组:int[,](矩形数组)
- 锯齿数组:int[][](数组的数组)

### 7.2 数组声明与初始化
基本语法
```c#
// 方式1:声明后初始化
int[] numbers1;
numbers1 = new int[5]; // 5个元素,默认值0

// 方式2:声明时初始化
int[] numbers2 = new int[] {1, 2, 3};

// 方式3:简化初始化
int[] numbers3 = {1, 2, 3, 4, 5};

// 方式4:指定大小
int[] numbers4 = new int[5] {1, 2, 3, 4, 5};
```

多维数组
```c#
// 二维数组(矩形数组)
int[,] matrix = new int[3,4]; // 3行4列

// 初始化二维数组
int[,] matrix2 = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

// 访问元素
int val = matrix2[1,2]; // 第2行第3列(6)
```

锯齿数组
```c#
// 声明锯齿数组
int[][] jagged = new int[3][];

// 初始化子数组
jagged[0] = new int[2] {1, 2};
jagged[1] = new int[3] {3, 4, 5};
jagged[2] = new int[4] {6, 7, 8, 9};

// 访问元素
int item = jagged[1][2]; // 5
```
### 7.3 数组操作
基本操作
```c#
int[] arr = {1, 2, 3, 4, 5};

// 访问元素
int first = arr[0]; // 1

// 修改元素
arr[1] = 10; // 数组变为[1,10,3,4,5]

// 获取长度
int len = arr.Length; // 5

// 遍历数组
for (int i = 0; i < arr.Length; i++) {
    Console.WriteLine(arr[i]);
}

foreach (int num in arr) {
    Console.WriteLine(num);
}
```

数组复制
```c#
int[] source = {1, 2, 3};
int[] dest = new int[3];

// 方法1:Array.Copy
Array.Copy(source, dest, source.Length);

// 方法2:Clone方法
int[] clone = (int[])source.Clone();

// 方法3:CopyTo
source.CopyTo(dest, 0);
```

数组排序与搜索
```c#
int[] numbers = {5, 3, 9, 1, 7};

// 快速排序
Array.Sort(numbers); // [1, 3, 5, 7, 9]

// 部分排序
Array.Sort(numbers, 1, 3); // 排序索引1开始的3个元素

// 自定义排序
Array.Sort(numbers, (x, y) => y.CompareTo(x)); // 降序[9,7,5,3,1]

// 二分查找(必须先排序)
int index = Array.BinarySearch(numbers, 7); // 返回3
if (index >= 0) {
    Console.WriteLine($"找到元素,位置:{index}");
}
```

 数组转换
 ```c#
 // 类型转换
object[] objArray = {1, "two", 3.0};
int[] intArray = Array.ConvertAll(objArray, x => Convert.ToInt32(x));

// 使用LINQ转换
var strArray = numbers.Select(x => x.ToString()).ToArray();
 ```

### 7.4 数组高级
**数组协变(仅适用于引用类型)**
```c#
object[] objArr = new string[10]; // 合法
// objArr[0] = 5; // 运行时抛出ArrayTypeMismatchException
```
**数组初始化器**
```c#
// 多维数组初始化
int[,] matrix = {
    {1, 2, 3},
    {4, 5, 6}
};

// 锯齿数组初始化
int[][] jagged = {
    new int[] {1, 2},
    new int[] {3, 4, 5}
};
```
**数组与Span**

Span:内存中连续的数据
```c#
int[] arr = {1, 2, 3, 4, 5};

// 创建Span
Span<int> span = arr.AsSpan();

// 切片操作
Span<int> slice = span.Slice(1, 3); // [2,3,4]
slice[0] = 10; // 原数组变为[1,10,3,4,5]
```

**数组与指针(unsafe)**
```c#
unsafe {
    int[] arr = {1, 2, 3};
    fixed (int* ptr = arr) {
        for (int i = 0; i < arr.Length; i++) {
            Console.WriteLine(*(ptr + i));
        }
    }
}
```
### 7.5 数组实用技巧

数组比较
```c#
int[] arr1 = {1, 2, 3};
int[] arr2 = {1, 2, 3};

// 比较引用
bool sameRef = arr1 == arr2; // false

// 比较内容
bool sameContent = arr1.SequenceEqual(arr2); // true
```
数组填充
```c#
int[] arr = new int[5];
Array.Fill(arr, 1); // [1,1,1,1,1]

// 部分填充
Array.Fill(arr, 0, 1, 3); // [1,0,0,0,1]
```

数组反转
```c#
int[] arr = {1, 2, 3, 4};
Array.Reverse(arr); // [4,3,2,1]

// 部分反转
Array.Reverse(arr, 1, 2); // [4,2,3,1]
```

数组清空
```c#
int[] arr = {1, 2, 3};
Array.Clear(arr, 0, arr.Length); // 所有元素设为0
```

## 8.集合

### 8.1 集合核心概念
集合与数组的区别
|特性	|数组	|集合|
|-|-|-|
|大小	|固定|	动态可变|
|功能|	基础操作	|丰富的数据操作方法|
|内存	|连续存储|	可能非连续|
|性能	|访问快(O(1))	|不同集合性能差异大|
|类型安全	|同类型元素	|泛型集合保证类型安全|

集合分类体系

```c#
IEnumerable<T> (可枚举)
├── ICollection<T> (基础集合)
│   ├── IList<T> (有序集合)
│   └── ISet<T> (唯一性集合)
└── IDictionary<TKey,TValue> (键值集合)
```
### 8.2 List
**核心特性**
​​动态数组​​:基于数组自动扩容
​​泛型支持​​:类型安全
​​丰富API​​:提供排序、搜索等操作
​​索引访问​​:支持下标访问(O(1))

默认构造初始容量为0,首次添加时扩容到4, 新容量 = 旧容量 * 2
**关键操作及时间复杂度**
|操作	|方法	|时间复杂度|
|-|-|-|
|添加元素	|Add(item)|	平均O(1)|
|批量添加|	AddRange(items)	|O(n)|
|插入元素	|Insert(index,item)|	O(n)|
|删除元素|	Remove(item)|	O(n)|
|按索引删除	|RemoveAt(index)|	O(n)|
|查找元素	|Contains(item)|	O(n)|
|索引访问|	[index]	|O(1)|

**性能优化**
```c#
// 1. 预分配容量
var list = new List<int>(10000);

// 2. 批量操作优于单个操作
list.AddRange(Enumerable.Range(1,1000));

// 3. 使用Capacity属性
list.Capacity = list.Count; // 释放多余空间

// 4. 排序优化
list.Sort(); // 快速排序 O(n log n)
```

### 8.3 Dictionary
**哈希表实现原理**
桶数组​​:存储链表头节点
​​哈希函数​​:GetHashCode()计算位置
​​冲突解决​​:链地址法处理碰撞
​​扩容机制​​:当元素数 > 容量*负载因子(默认0.75)时扩容
**核心操作**
```c#
Dictionary<string, int> dict = new Dictionary<string, int>();

// 添加元素(平均O(1))
dict.Add("Alice", 25); 
dict["Bob"] = 30;     // 替代语法

// 安全访问(避免异常)
if (dict.TryGetValue("Charlie", out int age)) {
    // 处理获取的值
}

// 删除键(平均O(1))
dict.Remove("Alice");

// 遍历方式
foreach (KeyValuePair<string, int> kvp in dict) {
    Console.WriteLine($"{kvp.Key}: {kvp.Value}");
}
```

**碰撞与性能优化**
```c#
// 1. 实现良好的Equals以及GetHashCode()
public class Person
{
    public string? Name { get; set; }
    public int Age { get; set; }

    public override bool Equals(object? obj)
    {
        return obj is Person person &&
               Name == person.Name &&
               Age == person.Age;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(Name, Age);
    }
}

// 2. 设置初始容量
var bigDict = new Dictionary<string, int>(100000);
// 3. 避免频繁扩容
dict.EnsureCapacity(50000);
```

### 8.4 HashSet 与 SortedSet
**HashSet**
特性:
- ​​唯一元素​​:自动去重
- ​​哈希实现​​:基于Dictionary实现
- ​​​​集合运算​​:支持并/交/差集
```c#
HashSet<int> setA = new HashSet<int>{1, 2, 3};
HashSet<int> setB = new HashSet<int>{3, 4, 5};

// 集合运算
setA.UnionWith(setB);       // 并集 {1,2,3,4,5}
setA.IntersectWith(setB);   // 交集 {3}
setA.ExceptWith(setB);      // 差集 {1,2}
```
**SortedSet**
- 红黑树实现​​:元素自动排序
- 范围查询​​:支持获取子集
- ​​查找效率​​:O(log n)


```c#
SortedSet<int> sorted = new SortedSet<int>{5, 3, 9};

// 获取范围视图
var subset = sorted.GetViewBetween(3, 7); // [3,5]

// 最小最大值
int min = sorted.Min; // 3
int max = sorted.Max; // 9
```
### 8.5 Queue与Stack 

**队列Queue**
```c#
Queue<string> queue = new Queue<string>();

// 入队
queue.Enqueue("First");
queue.Enqueue("Second");

// 出队
string item = queue.Dequeue(); // "First"

// 查看队首
string peek = queue.Peek(); // "Second"
```
**栈Stack**

```c#
Stack<int> stack = new Stack<int>();

// 压栈
stack.Push(1);
stack.Push(2);

// 弹栈
int top = stack.Pop(); // 2

// 查看栈顶
int current = stack.Peek(); // 1
```
### 8.6 线程安全集合
**Concurrent Collections**

```c#
// 1. 并发字典
ConcurrentDictionary<int, string> concurrentDict = new ConcurrentDictionary<int, string>();
concurrentDict.TryAdd(1, "Value");

// 2. 并发队列
ConcurrentQueue<int> concurrentQueue = new ConcurrentQueue<int>();
concurrentQueue.Enqueue(10);

// 3. 并发栈
ConcurrentStack<int> concurrentStack = new ConcurrentStack<int>();
concurrentStack.Push(20);

// 4. 并发包(无序集合)
ConcurrentBag<int> concurrentBag = new ConcurrentBag<int>();
concurrentBag.Add(30);
```

**同步包装器**
```c#
// 创建线程安全集合
var syncList = System.Collections.Synchronized(new List<int>());
var syncDict = System.Collections.Synchronized(new Dictionary<int, string>());

// 使用时仍需lock保证原子操作
lock (syncList.SyncRoot) {
    syncList.Add(1);
}
```
### 8.7 性能优化

预分配容量​​:减少扩容操作
```c#
new List<int>(1000);
new Dictionary<string,int>(5000);
```
避免装箱拆箱​​:使用泛型集合
```c#
// 错误:ArrayList导致装箱
ArrayList badList = new ArrayList();
badList.Add(1); // 装箱

// 正确:List<T>避免装箱
List<int> goodList = new List<int>();
goodList.Add(1); // 无装箱
```

批量操作​​:减少方法调用开销
```c#
// 优于多次Add
list.AddRange(items);
```
​​LINQ延迟执行​​:及时物化查询
```c#
// 立即执行
var result = source.Where(x => x > 0).ToList();
```

## 9.字符串
### 9.1 字符串基础
9.1.1  字符串特性
- 不可变性(Immutable)​​:字符串一旦创建就不能修改,所有"修改"操作都返回新字符串
- 引用类型​​:但具有值类型的某些特性
- ​​Unicode编码​​:支持多语言字符
- ​​字符串池(String Interning)​​:CLR对字面量字符串的优化机制

9.1.2 字符串创建方式
```c#
// 1. 直接赋值
string s1 = "Hello World";

// 2. 使用构造函数
char[] letters = { 'H', 'e', 'l', 'l', 'o' };
string s2 = new string(letters); // "Hello"

// 3. 重复字符
string s3 = new string('a', 5); // "aaaaa"

// 4. 从指针创建(unsafe)
unsafe {
    fixed (char* p = letters) {
        string s4 = new string(p); // "Hello"
    }
}
```

### 9.2 字符串常用操作
**9.2.1 基本操作**
```C#
// 长度获取
int len = "Hello".Length; // 5

// 索引访问
char first = "Hello"[0]; // 'H'

// 连接字符串
string concat = "Hello" + " " + "World"; // "Hello World"

// 大小写转换
string upper = "Hello".ToUpper(); // "HELLO"
string lower = "Hello".ToLower(); // "hello"
```

**9.2.2 字符串比较**

```C#
// 1. 值比较
bool equal = "Hello".Equals("hello"); // false
bool ignoreCase = "Hello".Equals("hello", StringComparison.OrdinalIgnoreCase); // true

// 2. Compare方法
int result = string.Compare("A", "B"); // -1 (A < B)

// 3. CompareTo方法
int result2 = "A".CompareTo("B"); // -1

// 4. 运算符
bool opEqual = "A" == "A"; // true
```
**9.2.3  字符串查找**

```C#
string text = "Hello World";

// 查找索引
int index1 = text.IndexOf('o'); // 4
int index2 = text.IndexOf("World"); // 6
int index3 = text.LastIndexOf('o'); // 7

// 检查包含
bool contains = text.Contains("World"); // true

// 开头/结尾检查
bool starts = text.StartsWith("Hello"); // true
bool ends = text.EndsWith("ld"); // true
```
**9.2.4 字符串修改**

```C#
string original = "Hello World";

// 截取
string sub1 = original.Substring(6); // "World"
string sub2 = original.Substring(0, 5); // "Hello"

// 插入
string inserted = original.Insert(5, " Beautiful"); // "Hello Beautiful World"

// 移除
string removed = original.Remove(5, 6); // "Hello"

// 替换
string replaced = original.Replace("World", "C#"); // "Hello C#"

// 修剪空白
string trimmed = "  Hello  ".Trim(); // "Hello"
string trimStart = "  Hello  ".TrimStart(); // "Hello  "
string trimEnd = "  Hello  ".TrimEnd(); // "  Hello"
```

### 9.3 字符串格式化
**9.3.1 复合格式化**
```C#
string.Format("Name: {0}, Age: {1}", "Alice", 25);
// "Name: Alice, Age: 25"
```
**9.3.2 字符串插值(C# 6.0+)**

```C#
string name = "Alice";
int age = 25;
string result = $"Name: {name}, Age: {age}";
// "Name: Alice, Age: 25"
```

**9.3.3 数值格式化**
```C#
// 数字格式化
string.Format("{0:N2}", 1234.5678); // "1,234.57"
string.Format("{0:D5}", 42); // "00042"
string.Format("{0:C}", 19.99); // "$19.99"

// 日期格式化
DateTime now = DateTime.Now;
string.Format("{0:yyyy-MM-dd}", now); // "2023-06-15"
```
### 9.4 字符串高级特性
**9.4.1 字符串构建器(StringBuilder)**
```C#
StringBuilder sb = new StringBuilder();
sb.Append("Hello");
sb.AppendLine(" World");
sb.AppendFormat("Today is {0:yyyy-MM-dd}", DateTime.Now);
string result = sb.ToString();
```

**9.4.2 字符串池(Interning)**
```C#
string a = "Hello";
string b = "Hello";
string c = new string(new[] { 'H', 'e', 'l', 'l', 'o' });

Console.WriteLine(object.ReferenceEquals(a, b)); // True (字符串池)
Console.WriteLine(object.ReferenceEquals(a, c)); // False

// 手动驻留
string d = string.Intern(c);
Console.WriteLine(object.ReferenceEquals(a, d)); // True
```
**9.4.3 逐字字符串(@)与转义字符**

```C#
// 普通字符串
string path1 = "C:\\Windows\\System32"; // 需要转义

// 逐字字符串
string path2 = @"C:\Windows\System32"; // 不需要转义

// 多行字符串
string multiLine = @"Line 1
Line 2
Line 3";
```
### 9.5 字符串编码与转换
**9.5.1 编码转换**
```C#
// 字符串转字节数组
byte[] utf8Bytes = Encoding.UTF8.GetBytes("Hello");
byte[] unicodeBytes = Encoding.Unicode.GetBytes("Hello");

// 字节数组转字符串
string fromUtf8 = Encoding.UTF8.GetString(utf8Bytes);
string fromUnicode = Encoding.Unicode.GetString(unicodeBytes);
```
**9.5.2 Base64编码**
```C#
// 编码
string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes("Hello"));

// 解码
string original = Encoding.UTF8.GetString(Convert.FromBase64String(base64));
```

### 9.6 字符串性能优化
**9.6.1  避免不必要的字符串操作**
```C#
// 不好:创建多个临时字符串
string result = "";
for (int i = 0; i < 100; i++) {
    result += i.ToString();
}

// 好:使用StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++) {
    sb.Append(i);
}
string finalResult = sb.ToString();
```
**9.6.2 比较优化**

```C#
// 不好:区分大小写的比较
if (input.ToLower() == "admin") { ... }

// 好:使用比较选项
if (input.Equals("admin", StringComparison.OrdinalIgnoreCase)) { ... }
```
**9.6.3 字符串分割优化**
```C#
// 不好:多次分割
string[] parts1 = csv.Split(',');
string[] parts2 = csv.Split(';');

// 好:一次性分割
char[] separators = { ',', ';' };
string[] parts = csv.Split(separators);
```
### 9.7 正则表达式

**9.7.1 基本用法**
```C#
using System.Text.RegularExpressions;

string pattern = @"\d+"; // 匹配数字
Regex regex = new Regex(pattern);

bool isMatch = regex.IsMatch("abc123"); // true
Match match = regex.Match("abc123");
string value = match.Value; // "123"
```
**9.7.2 常用模式**
```C#
// 电子邮件验证
bool isEmail = Regex.IsMatch(input, @"^[^@\s]+@[^@\s]+\.[^@\s]+$");

// 提取数字
MatchCollection matches = Regex.Matches("a1b2c3", @"\d");
foreach (Match m in matches) {
    Console.WriteLine(m.Value); // 1, 2, 3
}

// 替换
string clean = Regex.Replace("a1b2c3", @"\d", "_"); // "a_b_c_"
```

### 9.8 字符串安全
敏感信息处理
```C#
// 使用SecureString处理密码等敏感信息
SecureString securePwd = new SecureString();
foreach (char c in "password") {
    securePwd.AppendChar(c);
}
// 使用后立即清除
securePwd.Dispose();
```

## 10.控制台(Console )
### 10.1 基础
**10.1.1 Console 概述**
System.Console 类提供对标准输入、输出和错误流的访问
主要用于控制台应用程序的输入输出操作
所有方法都是静态的,无需实例化
**10.1.2 基本输入输出**
输出文本

```C#
Console.Write("Hello");       // 不换行输出
Console.WriteLine("World");    // 输出后换行
```

读取输入
```C#
string input = Console.ReadLine();  // 读取一行输入
int key = Console.Read();           // 读取单个字符(返回ASCII码)
ConsoleKeyInfo keyInfo = Console.ReadKey(); // 读取按键信息
```
### 10.2 格式化输出
**10.2.1 复合格式化**

```C#
string name = "Alice";
int age = 25;
Console.WriteLine("Name: {0}, Age: {1}", name, age);
```

**10.2.2 字符串插值(C# 6.0+)**

```C#
Console.WriteLine($"Name: {name}, Age: {age}");
```

**10.2.3 数值格式化**

```C#
double num = 1234.5678;
Console.WriteLine("{0:N2}", num);  // 1,234.57
Console.WriteLine("{0:C}", 19.99);  // $19.99
Console.WriteLine("{0:D5}", 42);    // 00042
```

### 10.3 控制台颜色设置
**10.3.1 颜色属性**

```C#
Console.ForegroundColor = ConsoleColor.Red;    // 前景色(文本)
Console.BackgroundColor = ConsoleColor.White;  // 背景色
Console.ResetColor(); // 重置为默认颜色   
```
**10.3.2 颜色示例**
```C#
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("警告信息");
Console.ResetColor();
```

### 10.4 控制台窗口控制
**10.4.1 窗口属性**
可能只在windows生效


```C#
Console.WindowWidth = 80;       // 设置窗口宽度
Console.WindowHeight = 30;      // 设置窗口高度
Console.BufferWidth = 100;      // 设置缓冲区宽度
Console.BufferHeight = 1000;    // 设置缓冲区高度
Console.Title = "我的控制台";    // 设置窗口标题
```

**10.4.2 光标控制**

```C#
Console.CursorVisible = false;  // 隐藏光标
Console.SetCursorPosition(10, 5); // 设置光标位置(列,行)
Console.CursorLeft = 20;        // 设置光标列位置
Console.CursorTop = 10;        // 设置光标行位置
```

### 10.5 高级功能
**10.5.1 控制台铃声**

```C#
Console.Beep();                 // 默认频率和时长
Console.Beep(800, 200);         // 频率(Hz), 时长(ms)
```

**10.5.2 编码设置**

```C#
Console.OutputEncoding = Encoding.UTF8;  // 设置输出编码
Console.InputEncoding = Encoding.UTF8;   // 设置输入编码
```

**10.5.3 清屏与进度显示**

```C#
Console.Clear();  // 清空控制台

// 简单进度条
for (int i = 0; i <= 100; i++)
{
    Console.Write($"\r进度: {i}% ");  // \r回到行首
    Thread.Sleep(50);
}
```
## 11.异常处理
### 11.1 异常处理基础
**11.1.1 异常概念**
异常​​:程序执行期间发生的意外情况

​​异常类​​:所有异常都继承自System.Exception

​​异常处理​​:捕获并处理异常,防止程序崩溃

**11.1.2 常见异常类型**
|异常类型|	描述|
|-|-|
|NullReferenceException	|尝试访问null对象成员|
|IndexOutOfRangeException|	数组/集合索引越界|
|ArgumentException|	方法参数无效|
|FormatException	|格式转换失败|
|IOException|	I/O操作错误|
|DivideByZeroException|	除零错误|

 ### 11.2 基本异常处理结构
** 11.2.1 try-catch 块**

```C#
try
{
    // 可能抛出异常的代码
    int result = 10 / int.Parse("0");
}
catch (DivideByZeroException ex)
{
    Console.WriteLine($"除零错误: {ex.Message}");
}
catch (FormatException ex)
{
    Console.WriteLine($"格式错误: {ex.Message}");
}
```
**11.2.2 finally**

```C#
FileStream file = null;
try
{
    file = File.Open("test.txt", FileMode.Open);
    // 文件操作
}
catch (IOException ex)
{
    Console.WriteLine($"IO错误: {ex.Message}");
}
finally
{
    file?.Close(); // 确保资源释放
}
```



**11.2.3 throw 语句**

```C#
// 重新抛出当前异常
catch (Exception ex)
{
    Console.WriteLine("记录错误");
    throw; // 保留原始调用栈
}

// 抛出新异常
if (value < 0)
    throw new ArgumentException("值不能为负");
```
### 11.3 异常处理高级特性
**11.3.1 异常筛选器 (C# 6.0+)**

```C#
try { /* ... */ }
catch (Exception ex) when (ex.Message.Contains("特定错误"))
{
    // 仅当条件满足时捕获
}
```

**11.3.2 自定义异常**

```C#
public class InvalidAccountException : Exception
{
    public InvalidAccountException() { }
    public InvalidAccountException(string message) : base(message) { }
    public InvalidAccountException(string message, Exception inner) 
        : base(message, inner) { }
}

// 使用自定义异常
throw new InvalidAccountException("账户无效");
```

**11.3.3 异常数据字典**

```C#
try { /* ... */ }
catch (Exception ex)
{
    ex.Data.Add("Timestamp", DateTime.Now);
    ex.Data.Add("User", "Admin");
    throw;
}
```

### 11.4 异常处理与资源管理

**11.4.1 using 语句**

```C#
using (var resource = new DisposableResource())
{
    // 自动调用Dispose(),即使抛出异常
}
```

**11.4.2 模式匹配 (C# 7.0+)**

```C#
try { /* ... */ }
catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException)
{
    Console.WriteLine("文件访问错误");
}
```

# 二.面向对象编程

## 1.类与对象

### 1.1 类和对象的基本概念
**类 (Class)**

- 类是创建对象的蓝图或模板
- 定义了对象的属性和行为
- 是面向对象编程的基本构建块

**对象 (Object)**
- 对象是类的实例
- 每个对象都有自己的状态(属性值)和行为(方法)
- 对象通过new关键字创建


```c#
// 定义一个类
public class Person
{
    // 类的成员
}

// 创建对象
Person person1 = new Person();
```

### 1.2 类的成员
**1.2.1 字段 (Fields)**
- 存储类或对象的数据
- 通常设为私有(private),通过属性访问


```c#
private string _name;
private int _age;
```

**1.2.2 属性 (Properties)**
- 提供对字段的安全访问
- 可以包含get和set访问器


```c#
private string _name;
public string Name
{
    get { return _name; }
    set { _name= value; }
}

// 自动属性(C# 3.0+)
public int Age { get; set; }
```

**1.2.3 方法 (Methods)**
- 定义类的行为
- 可以接受参数并返回值


```c#
public void SayHello()
{
    Console.WriteLine($"Hello, my name is {Name}");
}

public int CalculateAgeInMonths()
{
    return Age * 12;
}
```
**1.2.4 构造函数 (Constructors)**
- 用于初始化对象
- 与类同名,没有返回类型
- 可以重载

```c#
public Person()
{
    // 默认构造函数
}

public Person(string name, int age)
{
    Name = name;
    Age = age;
}
```
### 1.3 文档注释​​
为公共方法,属性添加注释,该注释能辅助编写代码时鼠标放上去查看解释

```c#
/// <summary>
/// 计算两个数的和
/// </summary>
/// <param name="a">第一个加数</param>
/// <param name="b">第二个加数</param>
/// <returns>两数之和</returns>
public int Add(int a, int b)
{
    return a + b;
}
```
### 1.4 访问修饰符
|关键字|	描述|
|-|-|
|public|	访问不受限制|
|private|	只能在当前类中访问|
|protected	|只能在当前类或派生类中访问|
|internal|	只能在当前程序集中访问|
|protected internal	|在当前程序集或派生类中可访问|
|private protected	|在当前程序集的派生类中可访问|
|file	|仅在当前文件中可访问|

### 1.5 静态成员
- 属于类而不是对象
- 通过类名访问,而不是对象实例
- 常用于工具类或共享数据

```c#
public class MathUtility
{
    public static double PI = 3.14159;
    
    public static int Add(int a, int b)
    {
        return a + b;
    }
}

// 使用静态成员
double pi = MathUtility.PI;
int sum = MathUtility.Add(5, 3);
```
### 1.6 静态类
静态类是一种特殊的类,具有以下核心特征:
- 不能被实例化​​(不能使用new创建对象)
- ​​只能包含静态成员​​(静态字段、静态方法、静态属性等)
- 隐式密封​​:静态类隐式是sealed的,尝试继承会编译错误

```c#
public static class MathUtility
{
    public static double PI = 3.14159;
}

// 使用静态成员
double pi = MathUtility.PI;
```

### 1.7 静态构造函数
- 在首次访问类时自动执行
- 每个应用程序域只执行一次
- 没有访问修饰符和参数

```c#
public class Logger
{
    private static readonly string logFile;
    
    // 静态构造函数
    static Logger()
    {
        logFile = $"log_{DateTime.Now:yyyyMMdd}.txt";
        Console.WriteLine("Logger初始化完成");
    }
    
    public static void Log(string message) { /*...*/ }
}
```

### 1.8 析构函数/终结器
- 在对象销毁前执行清理操作
- 不能手动调用,由垃圾回收器自动调用

```c#
~Person()
{
    // 清理代码
}
```

**现代对象销毁设计**
```c#
public class Resource : IDisposable
{
    public void Dispose() 
    {
        // 确定性释放资源
    }
}

// 使用示例
using (var res = new Resource()) 
{
    // 自动调用Dispose()
}
```

### 1.9 ref、out
**1.9.1 值传递 vs 引用传递​**
​​默认行为​​:C# 方法参数默认是​​值传递​​(传递副本)

```c#
void Modify(int x) { x = 100; }

int num = 10;
Modify(num);  // num 仍然是10
```
**1.9.2 ref 关键字​**
实现​​引用传递​​,方法内修改会影响原始变量,调用前​​必须初始化​​变量,方法声明和调用时都要加 ref。
```c#
void ModifyRef(ref int x) { x = 100; }

int num = 10;
ModifyRef(ref num);  // num 变为100
```

**1.9.3 out 关键字​**
用于从方法返回多个值(类似引用传递),调用前​​无需初始化​​变量,方法内​​必须赋值​​给out参数,方法声明和调用时都要加 out。

```c#
bool TryParse(string s, out int result) {
    if (int.TryParse(s, out result)) {
        return true;
    }
    return false;
}

int parsedValue;
if (TryParse("123", out parsedValue)) {
    Console.WriteLine(parsedValue); // 输出123
}
```
### 1.10 运算符重载

```c#
public class Vector2D
{
    public double X { get; set; }
    public double Y { get; set; }
    public Vector2D(double x, double y)
    {
        X = x;
        Y = y;
    }
    public static Vector2D operator +(Vector2D a, Vector2D b)
    {
        return new Vector2D(a.X + b.X, a.Y + b.Y);
    }
    public static Vector2D operator -(Vector2D a, Vector2D b)
    {
        return new Vector2D(a.X - b.X, a.Y - b.Y);
    }
}

public static void Main(string[] args)
{
    Vector2D v1 = new Vector2D(1, 2);
    Vector2D v2 = new Vector2D(3, 4);
    var n = (v1 + v2);
    Console.WriteLine($"new x:{n.X},new y:{n.Y}");
}
```
### 1.11 this关键字

**1.11.1 类索引器**
索引器(Indexer)是 C# 中的一种特殊成员,它允许类的实例像数组一样通过索引来访问。索引器类似于属性,但使用索引参数而不是属性名。
```c#
public class StringArray
{
    private string[] array = new string[10];
    
    // 索引器定义
    public string this[int index]
    {
        get
        {
            if (index < 0 || index >= array.Length)
                throw new IndexOutOfRangeException();
            return array[index];
        }
        set
        {
            if (index < 0 || index >= array.Length)
                throw new IndexOutOfRangeException();
            array[index] = value;
        }
    }
}

// 使用示例
StringArray myArray = new StringArray();
myArray[0] = "Hello";  // 调用set访问器
Console.WriteLine(myArray[0]);  // 调用get访问器,输出"Hello"



public class Matrix
{
    private int[,] data = new int[10, 10];
    
    public int this[int row, int col]
    {
        get { return data[row, col]; }
        set { data[row, col] = value; }
    }
}

// 使用示例
Matrix matrix = new Matrix();
matrix[0, 0] = 1;
Console.WriteLine(matrix[0, 0]);  // 输出1
```
**1.11.2 链式构造和指代当前**
```c#
public class User
{
    string uuid;
    string username;
    string password;

    public User()
    {
        uuid = Guid.NewGuid().ToString();
    }

    /// <summary>
    /// :this() 调用默认无参构造函数
    /// </summary>
    /// <param name="username"></param>
    public User(string username):this()
    {
        // 指示前传入的username赋值给当对象的username
        this.username = username;
    }
    public User(string username,string password):this(username)
    {
        this.password = password;
    }
}
```

**1.11.3 类拓展**
```c#
public class Program
{
    public static void Main(string[] args)
    {
        List<string> breakfast = new List<string>()
        {
            "煎饼果子",
            "包子",
            "油条",
            "豆浆",
            "稀饭",
            "炒饭",
            "炒面",
            "蛋挞",
            "牛奶",
            "面包",
        };
        Console.WriteLine($"今早吃:{breakfast.GetRandomItem()}");
    }

}

public static class ListExpand
{
    private readonly static Random random=new Random();
    public static T GetRandomItem<T>(this List<T> list)
    {
        return list[random.Next(0, list.Count)];
    }
}
```

### 1.12 部分类
将一个类分为两个文件编写,编译后为一个类
```c#
// File1.cs
public partial class MyClass
{
    public void Method1() { }
}

// File2.cs
public partial class MyClass
{
    public void Method2() { }
}
```

### 1.13 对象初始化器
```c#
//  Name 和 Age 为公开可写的属性
Person person = new Person 
{
    Name = "John",
    Age = 30
};
```

### 1.14 只读属性和只读字段
```c#
public class MyClass
{

    /// <summary>
    /// 只读字段:只能进行读取,无法重新赋值,且只能在构造函数中或字段上初始化
    /// </summary>
    private readonly List<string> _list = new List<string>();
    private readonly List<string> _list2;

    /// <summary>
    /// 只读属性:外部只能读取,不能修改
    /// </summary>
    public List<string> List3 { get; } = new List<string>();
    public MyClass()
    {
        _list2 = new List<string>();
    }
}
```
## 2.面向对象
### 2.1 面向对象三大特性

- 封装​​:隐藏对象内部细节,仅暴露必要接口
- ​​继承​​:子类继承父类特征和行为
- ​​多态​​:同一操作作用于不同对象产生不同行为

### 2.2 封装
两个核心思想:
- ​​数据隐藏​​:将对象的内部状态(数据)隐藏起来,不允许外部直接访问
- ​​行为暴露​​:通过公共方法(接口)提供对数据的受控访问

简单的封装示例:
```c#
public class User
{
    /// <summary>
    /// 自动属性,仅限内部使用
    /// </summary>
    public int Id { get; private set; }

    /// <summary>
    /// 私有字段,外部无法访问
    /// </summary>
    private string _username;

    /// <summary>
    /// 提供公开的访问属性进行暴露
    /// </summary>
    public string Username{
        get => _username;
    }

    /// <summary>
    /// 通过方法进行暴露
    /// </summary>
    /// <returns></returns>
    public string GetUsername()
    {
        return _username;
    }

    /// <summary>
    /// 设置用户名
    /// </summary>
    public void SetUsername(string username,string code)
    {
        if(string.IsNullOrEmpty(username)||string.IsNullOrEmpty(code)||!string.Equals(code,"123456"))
        {
            throw new ArgumentException("Username错误");
        }
        _username = username;
    }
}

```

### 2.3 继承
基于现有类创建新类,实现代码的重用和扩展

- ​​基类/父类​​:被继承的类
- 派生类/子类​​:继承自基类的新类
- "is-a"关系​​:子类是父类的一种特殊类型

**继承的基本语法**

```c#
// 基类(父类)
public class Animal
{
    public string Name { get; set; }
    
    public void Eat()
    {
        Console.WriteLine($"{Name} is eating.");
    }
}

// 派生类(子类)
public class Dog : Animal  // 使用冒号表示继承
{
    public void Bark()
    {
        Console.WriteLine($"{Name} is barking.");
    }
}
```
**成员继承**

1.子类自动获得父类的所有非私有成员(字段、属性、方法)
2.私有成员(private)不会被继承

**构造函数继承**
```c#
public class Animal
{
    public string Name { get; }
    
    // 基类构造函数
    public Animal(string name)
    {
        Name = name;
    }
}

public class Dog : Animal
{
    public string Breed { get; }
    
    // 派生类构造函数必须调用基类构造函数
    public Dog(string name, string breed) : base(name)  // 使用base关键字
    {
        Breed = breed;
    }
}
```
**方法重写(虚方法)**
```c#
public class Animal
{
    public virtual void MakeSound()  // virtual关键字表示可重写
    {
        Console.WriteLine("Some generic animal sound");
    }
}

public class Dog : Animal
{
    public override void MakeSound()  // override关键字表示重写
    {
        Console.WriteLine("Woof! Woof!");
    }
}

// 使用
Animal myDog = new Dog();
myDog.MakeSound();  // 输出 "Woof! Woof!" (多态)
```

**隐藏方法(new关键字)**
```c#
public class Animal
{
    public void Sleep()
    {
        Console.WriteLine("Animal is sleeping");
    }
}

public class Dog : Animal
{
    public new void Sleep()  // new关键字隐藏基类方法
    {
        Console.WriteLine("Dog is sleeping");
    }
}

// 使用
Animal animal = new Dog();
animal.Sleep();  // 输出 "Animal is sleeping" (没有多态)

Dog dog = new Dog();
dog.Sleep();     // 输出 "Dog is sleeping"
```
只有重写才有多态效果,方法重叠和隐藏方法都不行

**密封类和密封方法**
```c#
public sealed class FinalClass  // sealed关键字表示不能被继承
{
    // 类成员
}

public class BaseClass
{
    public virtual void Method()
    {
        // 可重写的方法
    }
}

public class DerivedClass : BaseClass
{
    public sealed override void Method()  // 密封方法,不能再被重写
    {
        // 方法实现
    }
}
```

**多继承与接口**
C#不支持多类继承,但可以通过接口实现
```c#
public interface IMovable
{
    void Move();
}

public interface ISpeakable
{
    void Speak();
}

public class Robot : IMovable, ISpeakable  // 实现多个接口
{
    public void Move()
    {
        Console.WriteLine("Robot is moving");
    }
    
    public void Speak()
    {
        Console.WriteLine("Beep boop");
    }
}
```

### 2.4 多态
**编译时多态(方法重载)**
```c#
public class Calculator
{
    // 方法重载:相同方法名,不同参数列表
    public int Add(int a, int b)
    {
        return a + b;
    }
    
    public double Add(double a, double b)
    {
        return a + b;
    }
    
    public int Add(int a, int b, int c)
    {
        return a + b + c;
    }
}

// 使用
var calc = new Calculator();
Console.WriteLine(calc.Add(1, 2));        // 调用int版本
Console.WriteLine(calc.Add(1.5, 2.5));    // 调用double版本
Console.WriteLine(calc.Add(1, 2, 3));    // 调用三参数版本
```
**运行时多态(方法重写)**

## 3.接口
接口是C#中一种引用类型,它定义了一组相关功能的契约(合同),但不提供具体实现
- ​​纯抽象​​:只包含方法、属性、事件和索引器的签名
- 多继承​​:类可以实现多个接口
- ​​解耦​​:分离定义与实现,降低耦合度
- ​​​​多态​​:实现接口的不同类可以以统一方式处理

### 3.1 定义接口
```c#
public interface ILogger
{
    // 方法签名
    void Log(string message);
    
    // 属性签名
    string LogLevel { get; set; }
    
    // 事件签名
    event Action<string> OnLogged;
    
    // 默认实现(C# 8.0+)
    void LogError(string error)
    {
        Log($"[ERROR] {error}");
        OnLogged?.Invoke(error);
    }
}
```

### 3.2 实现接口
```c#
public class FileLogger : ILogger
{
    private string _logLevel = "INFO";
    
    public string LogLevel
    {
        get => _logLevel;
        set => _logLevel = value;
    }
    
    public event Action<string> OnLogged;
    
    public void Log(string message)
    {
        File.AppendAllText("log.txt", $"[{LogLevel}] {DateTime.Now}: {message}\n");
        OnLogged?.Invoke(message);
    }
    
    // 可以选择重写默认实现
    public void LogError(string error)
    {
        Log($"[CRITICAL] {error}");
    }
}
```

### 3.3 显式接口实现
解决多个接口有相同成员名的问题
```c#
public interface IDatabase
{
    void Connect();
}

public interface IWebService
{
    void Connect();
}

public class DataService : IDatabase, IWebService
{
    // 显式实现IDatabase.Connect
    void IDatabase.Connect()
    {
        Console.WriteLine("Connecting to database...");
    }
    
    // 显式实现IWebService.Connect
    void IWebService.Connect()
    {
        Console.WriteLine("Connecting to web service...");
    }
    
    // 普通方法
    public void Connect()
    {
        Console.WriteLine("General connection...");
    }
}

// 使用
var service = new DataService();
service.Connect();               // 调用普通方法

((IDatabase)service).Connect();  // 调用IDatabase实现
((IWebService)service).Connect(); // 调用IWebService实现
```

### 3.4 接口继承
```c#
public interface IShape
{
    double CalculateArea();
}

public interface IDrawable : IShape
{
    void Draw();
}

public class Circle : IDrawable
{
    public double Radius { get; set; }
    
    public double CalculateArea()
    {
        return Math.PI * Radius * Radius;
    }
    
    public void Draw()
    {
        
    }
}
```

### 3.5 默认接口方法(C# 8.0+)
```c#
public interface IOrder
{
    decimal Amount { get; }
    DateTime Date { get; }
    
    // 默认实现
    string GetOrderInfo()
    {
        return $"Order on {Date:d} for {Amount:C}";
    }
}

public class OnlineOrder : IOrder
{
    public decimal Amount { get; set; }
    public DateTime Date { get; set; }
    
    // 可以选择不实现GetOrderInfo
}

// 使用
IOrder order = new OnlineOrder { Amount = 100.50m, Date = DateTime.Now };
Console.WriteLine(order.GetOrderInfo());  // 使用接口默认实现
```

## 4.抽象类
抽象类是C#中一种特殊的类,它不能被实例化,只能被继承。
1.不能被实例化​​:只能作为基类
​​2.可以包含抽象成员​​:没有实现的成员
​​3.可以包含具体实现​​:非抽象成员可以有实现
​​4.介于接口和普通类之间​​:比接口更具体,比普通类更抽象

### 4.1 定义抽象类

```c#
public abstract class Shape
{
    // 抽象方法(没有实现)
    public abstract double CalculateArea();
    
    // 普通方法(有实现)
    public void Display()
    {
        Console.WriteLine($"Area: {CalculateArea()}");
    }
    
    // 抽象属性
    public abstract string Name { get; }
    
    // 普通属性
    public string Color { get; set; } = "Black";
}
```
### 4.2 继承抽象类

```c#
public class Circle : Shape
{
    public double Radius { get; set; }
    
    // 必须实现抽象成员
    public override double CalculateArea()
    {
        return Math.PI * Radius * Radius;
    }
    
    public override string Name => "Circle";
    
    // 可以选择重写普通方法
    public override void Display()
    {
        Console.WriteLine($"Circle with radius {Radius} has area {CalculateArea():F2}");
    }
}
```

### 4.3 抽象类与构造方法
```c#
public abstract class Animal
{
    public string Species { get; }
    
    // 抽象类可以有构造方法
    protected Animal(string species)
    {
        Species = species;
    }
    
    public abstract void MakeSound();
}

public class Dog : Animal
{
    public Dog() : base("Canine") { }
    
    public override void MakeSound()
    {
        Console.WriteLine("Woof!");
    }
}
```

### 4.4 抽象类与密封方法
```c#
public abstract class Vehicle
{
    public abstract void StartEngine();
    
    // 密封方法(在派生类中不能被重写)
    public sealed void StopEngine()
    {
        Console.WriteLine("Engine stopped");
    }
}

public class Car : Vehicle
{
    public override void StartEngine()
    {
        Console.WriteLine("Car engine started");
    }
    
    // 不能重写StopEngine方法
}
```

### 4.5 抽象类与虚方法
```c#
public abstract class Database
{
    // 抽象方法(必须被重写)
    public abstract void Connect();
    
    // 虚方法(可以被重写)
    public virtual void Disconnect()
    {
        Console.WriteLine("Disconnected from database");
    }
}

public class SqlDatabase : Database
{
    public override void Connect()
    {
        Console.WriteLine("Connected to SQL Server");
    }
    
    // 可以选择重写虚方法
    public override void Disconnect()
    {
        Console.WriteLine("SQL Server connection closed");
        base.Disconnect();  // 调用基类实现
    }
}
```
### 4.6 抽象类与接口的比较
|特性	|抽象类|	接口|
|-|-|-|
|实例化|	不能	|不能|
|默认实现|	可以有	|C# 8.0+可以有默认实现|
|字段	|可以包含实例字段|	不能|
|构造方法	|可以有|	不能|
|访问修饰符	|可以控制成员访问级别	|默认为public|
|多继承|	不支持	|支持|
|版本控制	|添加新方法不影响现有子类	|添加新成员会破坏现有实现|

## 5.委托
### 5.1 描述
- 类型安全的函数指针​​:委托是一种引用类型,表示对具有特定参数列表和返回类型的方法的引用
- 回调机制​​:允许将方法作为参数传递
- ​​多播能力​​:一个委托可以引用多个方法

### 5.2 委托的声明与使用
```c#
using static TestDelegateDemo;

public class Program
{
    public static void Main(string[] args)
    {
        TestDelegateDemo testDelegateDemo = new TestDelegateDemo();
        testDelegateDemo.del += new MyDelegate(ShowMessage);
        testDelegateDemo.del += new MyDelegate(ShowMessage2);
        testDelegateDemo.del += new MyDelegate(ShowMessage3);
        // 也可进行删除
        // testDelegateDemo.del -= new MyDelegate(ShowMessage2);
        // 匿名方法
        testDelegateDemo.del += delegate (string msg)
        {
            Console.WriteLine("匿名方法:" + msg);
        };
        // Lambda表达式
        testDelegateDemo.del += (msg) =>
        {
            Console.WriteLine("Lambda表达式:" + msg);
        };
        testDelegateDemo.ShowAllMessage();
        // 直接调用
        //testDelegateDemo.del?.Invoke("Hello, World!");
    }

    public static void ShowMessage(string msg)
    {
        Console.WriteLine("sm1:"+msg);
    }
    public static void ShowMessage2(string msg)
    {
        Console.WriteLine("sm2:" + msg);
    }
    public static void ShowMessage3(string msg)
    {
        Console.WriteLine("sm3:" + msg);
    }
}

public class TestDelegateDemo
{
    public delegate void MyDelegate(string message);
    public MyDelegate? del;
    public void ShowAllMessage()
    {
        del?.Invoke("Hello, World!");
    }
}
```

### 5.3 内置委托类型
C# 提供了几种内置的通用委托类型,避免重复声明:

- Action:无返回值的方法(最多16个参数)
- Func:有返回值的方法(最多16个参数)
- Predicate:返回bool的方法(1个参数)

```c#
// 使用Action
Action<string> action = msg => Console.WriteLine(msg);
action("Hello Action!");

// 使用Func
Func<int, int, int> add = (a, b) => a + b;
int result = add(3, 5);  // 8

// 使用Predicate
Predicate<int> isEven = num => num % 2 == 0;
bool even = isEven(4);  // true
```

## 6.事件
### 6.1 描述
- 基于委托的发布-订阅模型​​:事件是委托的一种特殊形式,用于实现观察者模式
- 封装性​​:事件限制了外部对委托的直接访问
- ​​安全机制​​:防止外部直接调用或重置委托

### 6.2 标准事件模式
完整实现:
```c#
public class Program
{
    public static void Main(string[] args)
    {
        var monitor = new TemperatureMonitor();
        monitor.TemperatureChanged += (sender, e) =>
        {
            Console.WriteLine($"温度变化: {e.OldTemperature}°C -> {e.NewTemperature}°C");
        };
        monitor.CurrentTemperature = 10.0f;
        monitor.CurrentTemperature = 36.0f;
    }
}

/// <summary>
/// 气温监听器
/// </summary>
public class TemperatureMonitor
{
    public delegate void TemperatureChangedHandler(object sender, TemperatureEventArgs e);
    public event TemperatureChangedHandler? TemperatureChanged;
    private float _currentTemp;
    public float CurrentTemperature
    {
        get => _currentTemp;
        set
        {
            if (_currentTemp != value)
            {
                float oldTemp = _currentTemp;
                _currentTemp = value;
                //触发事件
                OnTemperatureChanged(oldTemp, _currentTemp);
            }
        }
    }
    protected virtual void OnTemperatureChanged(float oldTemp, float newTemp)
    {
        TemperatureChanged?.Invoke(this, new TemperatureEventArgs(oldTemp, newTemp));
    }
}

public class TemperatureEventArgs : EventArgs
{
    public float OldTemperature { get; }
    public float NewTemperature { get; }

    public TemperatureEventArgs(float oldTemp, float newTemp)
    {
        OldTemperature = oldTemp;
        NewTemperature = newTemp;
    }
}
```

简单实现
```c#
public class Program
{
    public static void Main(string[] args)
    {
        var monitor = new TemperatureMonitor();
        monitor.TemperatureChanged += (sender, e) =>
        {
            Console.WriteLine($"温度变化: {e.OldTemperature}°C -> {e.NewTemperature}°C");
        };
        monitor.CurrentTemperature = 10.0f;
        monitor.CurrentTemperature = 36.0f;
    }
}

/// <summary>
/// 气温监听器
/// </summary>
public class TemperatureMonitor
{
    public event EventHandler<TemperatureEventArgs>? TemperatureChanged;
    private float _currentTemp;
    public float CurrentTemperature
    {
        get => _currentTemp;
        set
        {
            if (_currentTemp != value)
            {
                float oldTemp = _currentTemp;
                _currentTemp = value;
                //触发事件
                OnTemperatureChanged(oldTemp, _currentTemp);
            }
        }
    }
    protected virtual void OnTemperatureChanged(float oldTemp, float newTemp)
    {
        TemperatureChanged?.Invoke(this, new TemperatureEventArgs(oldTemp, newTemp));
    }
}

public class TemperatureEventArgs : EventArgs
{
    public float OldTemperature { get; }
    public float NewTemperature { get; }

    public TemperatureEventArgs(float oldTemp, float newTemp)
    {
        OldTemperature = oldTemp;
        NewTemperature = newTemp;
    }
}
```

### 6.3 事件与委托的关键区别
|特性|委托	|事件|
|-|-|-|
|访问控制|	可被外部直接调用和赋值	|只能在声明类内部触发|
|多播能力	|支持|	支持|
|外部订阅/取消	|可以	|只能通过+=/-=操作|
|用途	|通用回调机制|	实现观察者模式|
|安全性	|低(可能被外部重置)|	高(封装了委托)|

## 7.结构体
结构体(struct)是C#中的一种值类型,与类(class)这种引用类型有着本质区别。
### 7.1  结构体基本概念
定义语法
```c#
public struct Point
{
    public int X;
    public int Y;
    
    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
    
    public void Move(int deltaX, int deltaY)
    {
        X += deltaX;
        Y += deltaY;
    }
}
```
核心特性:

- 值类型​​:存储在栈上(通常),直接包含数据
- 默认构造函数​​:编译器自动生成无参构造函数,不能自定义
- 继承限制​​:不能继承其他结构体或类,只能实现接口
- 不可为null​​:除非声明为可空类型(Nullable<Point>或Point?)
- ​​隐式密封​​:结构体隐式是密封的(sealed)

### 7.2 结构体与类的区别
|特性	|结构体|	类|
|-|-|-|
|类型	|值类型	|引用类型|
|存储位置	|栈(通常)	|堆|
|继承	|只能实现接口	|支持单继承和多接口实现|
|默认构造函数	|自动生成,不能自定义|	可以自定义|
|析构函数	|不支持|	支持|
|可为null	|必须显式声明可空|	默认可为null|
|赋值行为|	复制整个值|复制引用|
|大小限制	|建议小于16字节|	无限制|

### 7.3 结构体的构造函数
```c#
public struct Rectangle
{
    public double Width;
    public double Height;
    
    // 带参数的构造函数
    public Rectangle(double width, double height)
    {
        Width = width;
        Height = height;
    }
    
    // 编译错误:不能定义无参构造函数
    // public Rectangle() { }
    
    // 计算属性
    public double Area => Width * Height;
}

// 使用
var rect1 = new Rectangle(10, 20);  // 使用构造函数
var rect2 = new Rectangle();       // 使用默认构造函数,数值类型初始化为0
```

### 7.4 结构体的方法
```c#
public struct Vector3D
{
    public double X, Y, Z;
    
    public double Magnitude() => Math.Sqrt(X * X + Y * Y + Z * Z);
    
    public override string ToString() => $"({X}, {Y}, {Z})";
    
    public static Vector3D operator +(Vector3D a, Vector3D b) => 
        new Vector3D { X = a.X + b.X, Y = a.Y + b.Y, Z = a.Z + b.Z };
}
```
### 7.5 只读结构体(C# 7.2+)
```c#
public readonly struct ImmutablePoint
{
    public readonly int X;
    public readonly int Y;
    
    public ImmutablePoint(int x, int y)
    {
        X = x;
        Y = y;
    }
    
    public double Distance => Math.Sqrt(X * X + Y * Y);
    
    // 编译错误:不能修改只读结构体的字段
    // public void Move(int dx, int dy) { X += dx; Y += dy; }
}

// 使用
var point = new ImmutablePoint(3, 4);
Console.WriteLine(point.Distance);
```

### 7.6 ref结构体(C# 7.2+)
```c#
public ref struct StackOnlyStruct
{
    public int Value;
    
    public void Increment() => Value++;
}

// 使用
var stackOnly = new StackOnlyStruct { Value = 10 };
stackOnly.Increment();

// 不能将ref结构体装箱或放入堆中
// object obj = stackOnly; // 编译错误
// List<StackOnlyStruct> list; // 编译错误
```

## 8.记录
记录(Record)是C# 9.0引入的一种新的引用类型,主要用于简化不可变数据模型的创建。
### 8.1 基本概念
- 不可变性​​:默认属性为init-only
- 值语义相等​​:基于内容而非引用比较
- ​​简洁语法​​:减少样板代码
- ​​非破坏性修改​​:with表达式创建修改后的副本
- ​​ToString格式化​​:自动生成友好的ToString实现

```c#
// 位置记录(简洁语法)
public record Person(string FirstName, string LastName);

// 标准记录语法
public record Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
    
    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }
}
```

### 8.2 记录类型与类的区别
|特性	|记录类型|	类|
|-|-|-|
|相等性比较	|基于内容(值语义)	|基于引用(默认)|
|不可变性	|默认|	需要手动实现|
|复制修改	|内置with表达式支持|	需要手动实现|
|ToString实现	|自动生成友好格式|	默认返回类型名称|
|继承	|支持	|支持|
|解构	|内置支持|	需要手动实现|



### 8.3 记录类型的主要特性
1).位置记录


```c#
public record Point(double X, double Y);

// 使用
var p1 = new Point(1.0, 2.0);
var (x, y) = p1; // 解构
Console.WriteLine(p1); // 输出: Point { X = 1, Y = 2 }
```

2).非破坏性修改(with表达式)


```c#
var original = new Point(1.0, 2.0);
var modified = original with { X = 3.0 };

Console.WriteLine(original); // Point { X = 1, Y = 2 }
Console.WriteLine(modified); // Point { X = 3, Y = 2 }
```

3).值语义相等


```c#
var p1 = new Point(1.0, 2.0);
var p2 = new Point(1.0, 2.0);

Console.WriteLine(p1 == p2); // True
Console.WriteLine(ReferenceEquals(p1, p2)); // False
```

4).记录继承


```c#
public record Person(string FirstName, string LastName);
public record Student(string FirstName, string LastName, int Grade) 
  : Person(FirstName, LastName);



// 使用
var student = new Student("John", "Doe", 3);
Console.WriteLine(student); // Student { FirstName = John, LastName = Doe, Grade = 3 }
```

## 9.元组
元组是C#中的一种轻量级数据结构,用于临时组合多个值而无需创建专门的类或结构体。
```c#
// 未命名元组(Item1, Item2...)
var unnamedTuple = ("John", 30);

// 命名元组
var namedTuple = (Name: "John", Age: 30);

// 访问元素
Console.WriteLine(unnamedTuple.Item1); // "John"
Console.WriteLine(namedTuple.Age);    // 30

// 显式声明元组类型
(string, int) person1 = ("Alice", 25);
(string Name, int Age) person2 = ("Bob", 30);

// 作为方法返回类型
public (string, int) GetPerson() => ("Charlie", 35);
```

## 10.枚举
### 10.1基本使用

枚举(Enumeration)是C#中的一种值类型,用于定义一组命名常量。


```c#
// 基本枚举
public enum Weekday
{
    Monday,    // 默认值0
    Tuesday,   // 1
    Wednesday, // 2
    Thursday,  // 3
    Friday,    // 4
    Saturday,  // 5
    Sunday     // 6
}

// 带显式值的枚举
public enum StatusCode : int
{
    Success = 200,
    BadRequest = 400,
    Unauthorized = 401,
    NotFound = 404,
    ServerError = 500
}


// ==========================
// 声明
public enum Color { Red, Green, Blue }

// 使用
Color favorite = Color.Blue;

// 比较
if (favorite == Color.Blue)
{
    Console.WriteLine("蓝色");
}
```

### 10.2 标志枚举(Flags)


```c#
[Flags]
public enum Permissions
{
    None = 0,        // 0b_0000
    Read = 1,       // 0b_0001
    Write = 2,      // 0b_0010
    Execute = 4,    // 0b_0100
    Delete = 8,     // 0b_1000
    All = Read | Write | Execute | Delete // 0b_1111 (15)
}

// 组合权限
Permissions userPermissions = Permissions.Read | Permissions.Write;

// 检查权限
if (userPermissions.HasFlag(Permissions.Read))
{
    Console.WriteLine("拥有读取权限");
}

// 添加权限
userPermissions |= Permissions.Execute;

// 移除权限
userPermissions &= ~Permissions.Write;

// 检查多个权限
if ((userPermissions & (Permissions.Read | Permissions.Write)) == (Permissions.Read | Permissions.Write))
{
    Console.WriteLine("拥有读取和写入权限");
}
```

### 10.3 枚举描述特性


```c#
public enum LogLevel
{
    [Description("调试信息")]
    Debug,
    
    [Description("一般信息")]
    Info,
    
    [Description("警告信息")]
    Warning,
    
    [Description("错误信息")]
    Error
}

public static string GetDescription(this Enum value)
{
    var field = value.GetType().GetField(value.ToString());
    var attribute = field?.GetCustomAttributes(typeof(DescriptionAttribute), false)
                    .FirstOrDefault() as DescriptionAttribute;
    return attribute?.Description ?? value.ToString();
}

// 使用
Console.WriteLine(LogLevel.Warning.GetDescription()); // "警告信息"
```

### 10.4 枚举遍历


```c#
foreach (Weekday day in Enum.GetValues(typeof(Weekday)))
{
    Console.WriteLine($"{day} = {(int)day}");
}

// 获取所有枚举名称
string[] colorNames = Enum.GetNames(typeof(Color));
```



© 2026 XyzRgb.space · 本页内容为个人学习记录,如有错漏欢迎指正。