1. 类(Class)的本质与核心价值
在C#的世界里,类(Class)就像是一个万能模具,它能塑造出具有相同特征和行为的对象实体。想象你是一家汽车工厂的设计师,类就是你的设计图纸——它定义了每辆汽车应有的属性(如颜色、排量)和行为(如加速、刹车)。而根据设计图纸生产出来的具体车辆,就是类的实例(Instance)。
关键理解:类不是具体存在的东西,而是创建对象时依据的模板规范。就像你不能把设计图纸当汽车开,但可以根据图纸造出无数辆真实汽车。
类的核心价值体现在三个方面:
- 封装复杂性:把发动机工作原理、变速箱逻辑这些复杂实现藏在类内部,外部只需知道油门和刹车踏板怎么用
- 提高复用性:一套汽车设计图纸可以用于生产线上所有同型号车辆
- 建立关系体系:通过继承机制,轿车类、SUV类可以共享基础车辆类的通用特性
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 类的结构解剖与语法细节
2.1 标准类定义模板
csharp复制[访问修饰符] class 类名 [: 父类名] [, 接口列表]
{
// 字段(存储数据)
private string _model;
// 属性(控制字段访问)
public int CurrentSpeed { get; private set; }
// 方法(定义行为)
public void Accelerate(int increment)
{
CurrentSpeed += increment;
}
// 构造函数(初始化逻辑)
public Car(string model)
{
_model = model;
}
}
2.2 访问修饰符的实战选择
public:像公园长椅谁都能用(跨程序集可见)private:像自家卧室仅内部可用(默认类成员修饰符)protected:家族传承的祖传秘方(子类可访问)internal:公司内部通讯录(同一程序集可见)protected internal:家族企业里的共享资源
经验法则:从最严格权限开始(private),随着实际需要逐步放宽。就像你不会把银行账户密码设为public一样。
3. 类关系网络构建技巧
3.1 继承——家族血脉传承
csharp复制class Vehicle { /* 基础功能 */ }
class Car : Vehicle { /* 扩展特性 */ }
class ElectricCar : Car { /* 特殊实现 */ }
继承链条就像生物进化树:
System.Object是所有类的终极祖先- 单继承限制:C#不允许多重继承(一个类不能同时继承多个父类)
- 密封类(sealed)是进化终点,禁止再派生新类
3.2 接口——能力契约系统
csharp复制interface IDrivable { void Drive(); }
class SmartCar : IDrivable { public void Drive() { /* 自动驾驶逻辑 */ } }
接口使用要点:
- 命名习惯用"I"前缀(如
IDisposable) - 实现接口必须履行全部契约方法
- 新版C#支持接口默认实现(类似多重继承效果)
3.3 组合优于继承原则
当出现"是不是"关系时用继承(轿车是汽车),"有没有"关系时用组合:
csharp复制class Engine { /* 发动机实现 */ }
class Car
{
private Engine _engine; // 组合关系
public Car() => _engine = new Engine();
}
4. 高级类设计模式
4.1 静态类的正确打开方式
csharp复制static class MathUtility
{
public static double PI = 3.1415926;
public static int Add(int a, int b) => a + b;
}
// 使用:MathUtility.Add(2,3)
适用场景:
- 工具方法集合(如数学计算)
- 全局配置容器
- 扩展方法挂载点
4.2 抽象类的精妙平衡
csharp复制abstract class Shape
{
public abstract double Area(); // 抽象方法
public void Print() => Console.WriteLine(Area());
}
class Circle : Shape { /* 必须实现Area */ }
与接口的核心区别:
- 抽象类可以包含实现代码
- 抽象类可以有字段
- 抽象类构造函数可以包含逻辑
4.3 分部类的工程化应用
csharp复制// File1.cs
partial class DataProcessor
{
public void Process() { /* ... */ }
}
// File2.cs
partial class DataProcessor
{
public void Validate() { /* ... */ }
}
典型使用场景:
- 大型类分多人协作开发
- 自动生成代码与手工代码分离
- WinForms设计器后台代码
5. 类生命周期管理实战
5.1 构造函数设计模式
csharp复制class DatabaseConnector
{
private string _connectionString;
// 主构造函数
public DatabaseConnector(string connStr) => _connectionString = connStr;
// 便捷构造函数
public DatabaseConnector() : this("default_connection") {}
// 静态工厂方法
public static DatabaseConnector CreateFromConfig()
=> new(ConfigurationManager.ConnectionStrings["Default"].ConnectionString);
}
5.2 终结器与Dispose模式
csharp复制class ResourceHolder : IDisposable
{
private IntPtr _handle;
~ResourceHolder() => Dispose(false); // 终结器
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_handle != IntPtr.Zero)
{
CloseHandle(_handle);
_handle = IntPtr.Zero;
}
}
}
5.3 对象初始化语法糖
csharp复制var student = new Student
{
Name = "张三",
Age = 20,
Courses = new List<string> { "数学", "物理" }
};
等效于:
csharp复制var temp = new Student();
temp.Name = "张三";
temp.Age = 20;
temp.Courses = new List<string> { "数学", "物理" };
Student student = temp;
6. 类设计中的典型陷阱
6.1 循环引用灾难
csharp复制class Parent { public Child Baby { get; set; } }
class Child { public Parent Mother { get; set; } }
// 使用时会内存泄漏!
解决方案:
- 弱引用模式(WeakReference)
- 事件解耦
- 重构为单向关系
6.2 过度公开内部状态
错误示范:
csharp复制class BankAccount
{
public decimal Balance { get; set; } // 危险!
}
正确做法:
csharp复制class BankAccount
{
private decimal _balance;
public decimal Balance => _balance; // 只读暴露
public void Deposit(decimal amount)
{
if(amount <= 0) throw new ArgumentException();
_balance += amount;
}
}
6.3 值类型与引用类型混淆
csharp复制class RefType { public int Value; }
struct ValType { public int Value; }
void Modify(RefType r, ValType v)
{
r.Value = 100;
v.Value = 100;
}
var refObj = new RefType();
var valObj = new ValType();
Modify(refObj, valObj);
Console.WriteLine(refObj.Value); // 输出100
Console.WriteLine(valObj.Value); // 输出0(未改变)
7. 现代C#类特性演进
7.1 记录类型(Record)
csharp复制public record Person(string Name, int Age);
// 编译器自动生成:
// - 不可变属性
// - 基于值的相等比较
// - 复制构造函数
// - 解构方法
与普通类的核心区别:
- 默认不可变(immutable)
- 值语义相等比较
- 完美支持模式匹配
7.2 模式匹配增强
csharp复制public decimal CalculateArea(object shape) => shape switch
{
Circle c => Math.PI * c.Radius * c.Radius,
Rectangle r => r.Width * r.Height,
_ => throw new ArgumentException()
};
7.3 主构造函数(Primary Constructor)
csharp复制class Student(string name, int age) // C# 12特性
{
public string Name { get; } = name;
public int Age { get; } = age;
public override string ToString() => $"{Name} ({Age})";
}
8. 类设计最佳实践清单
- 单一职责原则:一个类只做一件事(如
Order类负责订单数据,OrderValidator负责验证) - 开闭原则:对扩展开放,对修改关闭(通过继承/组合扩展,而非修改源码)
- 依赖倒置:依赖抽象而非具体实现(参数用
IEnumerable<T>而非List<T>) - 命名规范:
- 类名用名词或名词短语(
Customer、StringBuilder) - 方法名用动词或动词短语(
CalculateTotal、SaveToDatabase)
- 类名用名词或名词短语(
- 大小控制:理想类规模在300行以内(超过应考虑拆分)
- 测试友好设计:
- 依赖通过构造函数注入
- 避免静态全局状态
- 核心逻辑与IO操作分离
9. 性能关键场景优化
9.1 避免过度装箱
csharp复制// 错误做法:引发装箱操作
ArrayList list = new();
list.Add(42); // int被装箱为object
// 正确做法:使用泛型集合
List<int> betterList = new();
betterList.Add(42); // 无装箱
9.2 结构体(struct)使用场景
csharp复制public struct Point
{
public double X, Y;
public Point(double x, double y) => (X, Y) = (x, y);
}
适用条件:
- 小于16字节的小型数据结构
- 逻辑上表示单个值(如坐标、RGB颜色)
- 不需要继承多态
- 频繁创建销毁且对GC压力敏感
9.3 对象池模式
csharp复制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);
}
适用场景:数据库连接、线程等重量级对象管理
10. 真实项目中的类设计案例
10.1 电商订单系统
csharp复制public abstract class OrderBase
{
public string OrderId { get; }
public DateTime CreateTime { get; }
public abstract decimal CalculateTotal();
}
public class PhysicalProductOrder : OrderBase
{
public List<ProductItem> Items { get; }
public override decimal CalculateTotal() => Items.Sum(x => x.Price * x.Quantity) + 15m; // 运费
}
public class DigitalProductOrder : OrderBase
{
public List<DigitalItem> Downloads { get; }
public override decimal CalculateTotal() => Downloads.Sum(x => x.Price) * 0.9m; // 数字商品9折
}
10.2 游戏角色系统
csharp复制public interface ICharacter
{
void Move(Vector2 direction);
void TakeDamage(float amount);
}
public abstract class CharacterBase : ICharacter
{
public float Health { get; protected set; }
public Vector2 Position { get; private set; }
public virtual void Move(Vector2 direction)
=> Position += direction * MoveSpeed;
public virtual void TakeDamage(float amount)
=> Health = Math.Max(0, Health - amount);
}
public class Player : CharacterBase
{
public override void TakeDamage(float amount)
{
base.TakeDamage(amount * 0.8f); // 玩家有20%减伤
if(Health <= 0) GameOver();
}
}
10.3 物联网设备抽象
csharp复制public abstract class IoTDevice
{
public string DeviceId { get; }
public DeviceStatus Status { get; protected set; }
public abstract Task<CommandResult> ExecuteCommandAsync(string command);
protected virtual void ValidateCommand(string command)
{
if(string.IsNullOrWhiteSpace(command))
throw new ArgumentException("命令不能为空");
}
}
public class SmartThermostat : IoTDevice
{
private float _currentTemp;
public override async Task<CommandResult> ExecuteCommandAsync(string command)
{
ValidateCommand(command);
// 解析温度设置命令
if(command.StartsWith("SET_TEMP:"))
{
var temp = float.Parse(command.Split(':')[1]);
await SetTemperatureAsync(temp);
return CommandResult.Success;
}
return CommandResult.Failed("未知命令");
}
}
