作为一名有十年.NET开发经验的工程师,我经常遇到开发者对C#某些核心概念理解模糊的情况。本文将系统梳理值类型/引用类型、泛型、集合操作、内存管理等关键知识点,并结合实际工程案例展示如何正确应用这些特性。
C#的类型系统以object为根节点,派生两大分支:
csharp复制// 简单类型
int age = 30;
double price = 99.99;
// 结构体
struct Point {
public int X;
public int Y;
}
// 枚举
enum Weekday { Monday, Tuesday }
csharp复制// 类
class Person {
public string Name;
}
// 接口
interface ILogger {
void Log(string message);
}
// 字符串
string greeting = "Hello";
// 数组
int[] numbers = new int[10];
关键理解:对于
MyClass obj = new MyClass();
obj变量(引用)存储在栈new MyClass()实例存储在堆=操作将堆地址赋给栈变量
csharp复制class Program {
struct Point { public int X, Y; }
static void Main() {
// 值类型(栈)
int localInt = 42;
// 引用类型实例(堆)
var person = new Person();
// 值类型作为类成员(随实例在堆)
person.Age = 30;
}
}
class Person {
public int Age; // 值类型在堆
}
| 类型 | 特点 | 时间复杂度 | 典型场景 |
|---|---|---|---|
| 数组 | 固定长度 | O(1)访问 | 已知元素数量 |
| List |
动态扩容 | O(1)访问 | 通用集合 |
| ObservableCollection | 通知变更 | O(n)插入删除 | WPF绑定 |
csharp复制var devices = new List<string> { "PLC-A", "Sensor-B" };
// 批量操作
devices.AddRange(new[] { "Motor-C", "Drive-D" });
// 条件删除
devices.RemoveAll(d => d.Contains("Sensor"));
// 容量优化(避免频繁扩容)
devices.Capacity = 100;
// 安全访问
if(devices.Count > 5) {
var item = devices[5];
}
csharp复制// 定义可观察集合
var obsCollection = new ObservableCollection<Device>();
// 注册变更通知
obsCollection.CollectionChanged += (sender, e) => {
Console.WriteLine($"变更类型: {e.Action}");
if(e.NewItems != null) {
foreach(Device item in e.NewItems)
Console.WriteLine($"新增: {item.Name}");
}
};
// 触发通知的操作
obsCollection.Add(new Device("Motor-X"));
obsCollection.RemoveAt(0);
重要提示:当集合元素是引用类型时,修改对象属性不会触发CollectionChanged事件。需要实现INotifyPropertyChanged接口实现属性级通知。
csharp复制public class Repository<T> where T : IEntity {
private List<T> _items = new List<T>();
public void Add(T item) {
_items.Add(item);
}
public T GetById(int id) {
return _items.FirstOrDefault(i => i.Id == id);
}
}
// 使用示例
var userRepo = new Repository<User>();
var productRepo = new Repository<Product>();
csharp复制public static T Max<T>(T a, T b) where T : IComparable<T> {
return a.CompareTo(b) > 0 ? a : b;
}
// 调用示例
int maxInt = Max(10, 20);
string maxStr = Max("A", "B");
csharp复制// 多条件约束
public class Processor<T> where T : class, IProcessable, new() {
public void Process() {
var instance = new T();
instance.Initialize();
instance.Execute();
}
}
// 接口约束
public interface ILogger<T> {
void Log(T message);
}
// 协变/逆变
public interface IContainer<out T> {
T GetItem();
}
| 阶段 | 行为 | 示例 |
|---|---|---|
| 分配 | CLR在堆上分配内存 | new MyClass() |
| 使用 | 通过引用访问对象 | obj.DoSomething() |
| 不可达 | 失去所有引用 | 局部变量离开作用域 |
| 回收 | GC释放内存 | 自动触发 |
csharp复制// IDisposable模式标准实现
public class FileHandler : IDisposable {
private FileStream _fileStream;
private bool _disposed = false;
public FileHandler(string path) {
_fileStream = new FileStream(path, FileMode.Open);
}
protected virtual void Dispose(bool disposing) {
if(!_disposed) {
if(disposing) {
// 释放托管资源
_fileStream?.Dispose();
}
// 释放非托管资源
// (本例无额外非托管资源)
_disposed = true;
}
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
~FileHandler() {
Dispose(false);
}
}
// 使用示例
using(var handler = new FileHandler("test.txt")) {
// 操作文件
} // 自动调用Dispose()
mermaid复制graph TD
A[需要拷贝对象] --> B{包含引用类型字段?}
B -->|否| C[浅拷贝足够]
B -->|是| D{修改副本是否应影响原对象?}
D -->|否| E[必须深拷贝]
D -->|是| F[浅拷贝即可]
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 手动实现 | 完全控制 | 维护成本高 | 简单对象结构 |
| 序列化 | 自动化 | 性能开销大 | 复杂对象图 |
| 表达式树 | 高性能 | 实现复杂 | 频繁拷贝场景 |
csharp复制public static T DeepCopy<T>(T obj) {
using var stream = new MemoryStream();
var formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
csharp复制public static class DeepCopyExpression {
public static T Copy<T>(T original) {
return Copier<T>.Copy(original);
}
private static class Copier<T> {
private static readonly Func<T, T> _copier;
static Copier() {
var param = Expression.Parameter(typeof(T));
var bindings = new List<MemberBinding>();
foreach(var prop in typeof(T).GetProperties()) {
if(prop.CanWrite) {
bindings.Add(Expression.Bind(
prop,
Expression.Property(param, prop)));
}
}
_copier = Expression.Lambda<Func<T, T>>(
Expression.MemberInit(
Expression.New(typeof(T)),
bindings),
param).Compile();
}
public static T Copy(T original) => _copier(original);
}
}
值类型设计原则:
对象池模式:
csharp复制public class ObjectPool<T> where T : new() {
private readonly ConcurrentBag<T> _pool = new();
public T Get() => _pool.TryTake(out var item) ? item : new T();
public void Return(T item) => _pool.Add(item);
}
在最近的高频交易系统开发中,我们通过将关键数据结构从class改为struct,配合对象池重用,使GC暂停时间从平均15ms降至2ms以下。这印证了深入理解类型系统对性能优化的关键作用。