一、数据类型与内存管理
1. 值类型(Value Types)
- 定义:直接存储数据本身,存放在**栈(stack)**中。
- 包含类型:
- 基本类型:
int
,float
,double
,bool
,char
,byte
,short
,long
- 结构体(struct):用户自定义的值类型,需继承自
System.ValueType
。 - 枚举(enum):本质上是
int
的别名,但可定义命名常量。
- 基本类型:
- 关键特性:
- 赋值/传递时创建副本:
int a = 10; int b = a; // b是a的副本,修改b不影响a
- 方法参数传递:值类型参数传递的是值的副本,方法内修改不影响原始变量。
void Modify(int x) { x = 20; } int num = 10; Modify(num); // num仍为10
- 结构体的注意事项:
- 结构体可以有构造函数、方法,但实例化时不需要
new
(除非显式调用构造函数)。 - 避免定义过大结构体(建议不超过16字节),否则性能可能下降。
- 结构体可以有构造函数、方法,但实例化时不需要
- 赋值/传递时创建副本:
2. 引用类型(Reference Types)
- 定义:存储对数据的引用(内存地址),数据本身存放在**堆(heap)**中。
插入知识:堆和栈
栈Stack | 堆Heap | |
空间 | 小 | 大 |
速度 | 快 | 慢 |
内存分配释放 | 自动 | 手动 |
存储 | 局部变量、函数参数、地址 | 动态分配对象、大型数据结构 |
生命周期 | 函数调用结束后销毁 | 手动释放/垃圾回收器 |
特点 | LIFO(后进先出) | 动态分配 |
分配顺序 | 按序分配 | 动态寻找可用内存块 |
定义一个P类型变量小p | 小p变量存储在栈内 | 大P对象内容存储在堆内 |
- 包含类型:
- 类(class):如
string
,object
, 自定义类。 - 接口(interface)、委托(
delegate
)、数组(array
)、dynamic
类型。
- 类(class):如
- 关键特性:
- 赋值/传递时传递引用:
Person p1 = new Person { Name = "Alice" }; Person p2 = p1; // p2和p1指向同一对象 p2.Name = "Bob"; // p1.Name也变为"Bob"
- 方法参数传递:引用类型参数传递的是引用的副本,方法内修改对象会影响原始对象。
void Modify(Person p) { p.Name = "Bob"; } Person person = new Person { Name = "Alice" }; Modify(person); // person.Name变为"Bob"
- 赋值/传递时传递引用:
3. 值类型与引用类型的对比
特性 | 值类型 | 引用类型 |
---|---|---|
内存位置 | 栈(stack) | 堆(heap) |
赋值/传递 | 创建副本 | 传递引用的副本 |
默认值 | 0 (数值类型)、false (bool)、\0 (char) | null |
二、类与对象
1. 类(class)基础
- 定义:
public class Person { // 成员变量(字段) public string Name { get; set; } // 自动属性 private int age; // 私有字段 // 构造函数 public Person(string name) { Name = name; } // 方法 public void SayHello() { Console.WriteLine($"Hello, {Name}!"); } }
- 关键点:
- 访问修饰符:
public
(公开)、private
(私有)、protected
(保护)、internal
(当前程序集可见)。 - 构造函数:无返回类型,名称与类名相同;可重载。
- 析构函数:
~ClassName()
,用于资源清理(非必须,GC自动回收)。
- 访问修饰符:
2. 结构体(struct)
- 定义:
public struct Point { public int X; public int Y; public Point(int x, int y) { X = x; Y = y; } }
- 与类的区别:
- 结构体是值类型,类是引用类型。
- 结构体默认无默认构造函数,但可显式定义。
- 结构体不能继承其他结构体/类,但可实现接口。
3. 对象实例化
- 类:需使用
new
关键字。Person person = new Person("Alice");
- 结构体:可直接赋值或使用
new
(显式调用构造函数)。Point point = new Point(1, 2); // 显式调用构造函数 Point point2 = default; // 默认值(X=0, Y=0)
三、方法与参数
1. 方法定义
- 返回值:
void
表示无返回值,其他类型需返回值。- 参数传递方式:
- 值传递(默认):值类型传副本,引用类型传引用的副本。
- 引用传递:使用
ref
或out
关键字。void Modify(ref int x) { x = 20; } int num = 10; Modify(ref num); // num变为20
- 参数传递方式:
2. 参数类型
类型 | 说明 | 示例 |
---|---|---|
值类型参数 | 传递值的副本,修改不影响原变量 | void Add(int a) |
**引用类型参数 | 传递引用的副本,修改对象会影响原对象 | void Update(Person p) |
ref/out参数 | 传递变量的引用,允许修改原变量 | void Swap(ref int a, ref int b) |
params参数 | 支持可变数量的参数(只能是最后一个参数) | void Sum(params int[] numbers) |
可选参数 | 定义默认值,调用时可省略 | void Print(int num = 0) |
四、异常处理
1. try-catch-finally
- 语法:
try { // 可能抛出异常的代码 } catch (ExceptionType1 ex) { // 处理特定异常 } catch (ExceptionType2 ex) { // 其他异常处理 } finally { // 总会执行的清理代码(无论是否抛出异常) }
- 注意事项:
- 捕获异常时,优先捕获具体异常类型(如
FileNotFoundException
),而非直接捕获Exception
。 - 使用
throw;
重新抛出当前异常(保留堆栈信息),避免throw ex;
(会丢失原始堆栈)。
- 捕获异常时,优先捕获具体异常类型(如
2. 自定义异常
- 定义:
public class MyException : Exception { public MyException(string message) : base(message) { } }
五、集合与泛型
1. 常用集合类
类型 | 说明 | 示例 |
---|---|---|
List<T> | 可变大小的动态数组 | List<int> numbers = new List<int>(); |
Array | 固定大小的数组 | int[] arr = new int[5]; |
Dictionary<TKey, TValue> | 键值对集合 | Dictionary<string, int> dict = new(); |
Queue<T> | 先进先出(FIFO) | Queue<string> queue = new(); |
Stack<T> | 后进先出(LIFO) | Stack<int> stack = new(); |
2. 泛型(Generics)
- 作用:提供类型安全的集合和方法,避免类型转换。
- 示例:
List<string> names = new List<string>(); // 泛型集合 public T Find<T>(List<T> list, T item) { ... } // 泛型方法
六、其他关键细节
1. 装箱与拆箱(Boxing/Unboxing)
- 装箱:将值类型转换为
object
或接口类型。int num = 10; object boxed = num; // 装箱(栈→堆)
- 拆箱:将
object
转回值类型。int unboxed = (int)boxed; // 拆箱(堆→栈)
- 性能影响:频繁装箱拆箱可能导致性能问题,应尽量避免。
2. 命名空间与using
- 作用:组织代码,避免命名冲突。
- 示例:
using System; // 引入System命名空间 using MyNamespace; // 引入自定义命名空间
3. 属性(Properties)
- 定义:
public class Person { private string name; public string Name { get { return name; } set { name = value; } } }
- 自动属性:
public string Name { get; set; } // 自动生成字段
七、之后的规划
回顾数据结构和算法基础:
实现链表(LinkedList<T>
)、栈、队列;排序算法(冒泡排序、快速排序);二分查找、递归问题(斐波那契、阶乘)等等等等,一天刷2道leetcode外加2道Acwing
熟练使用C#特性:
- 使用
List<T>
和Dictionary<TKey,TValue>
实现缓存。 - 用委托和事件实现观察者模式。
- 通过
yield return
实现迭代器块。 - 。。。。。。。