C# 泛型(Generics)
下面是一个从专业开发角度出发、全面深入、附权威链接的【C# 泛型(Generic)】学习与参考指南。
1️⃣ 什么是泛型?(Generics)
泛型(Generics)是 .NET 提供的一种类型参数化机制,允许类、接口、方法在声明时不指定具体数据类型,而是在使用时指定,从而提升:
- 类型安全
- 性能(避免装箱/拆箱)
- 代码复用性
📘 官方定义:https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/
2️⃣ 泛型的语法结构
2.1 泛型类
public class GenericBox<T>
{
public T Value { get; set; }
}
使用:
var intBox = new GenericBox<int> { Value = 123 };
var strBox = new GenericBox<string> { Value = "Hello" };
2.2 泛型方法
public T Max<T>(T a, T b) where T : IComparable<T>
{
return a.CompareTo(b) > 0 ? a : b;
}
2.3 泛型接口
public interface IRepository<T>
{
void Add(T item);
T Get(int id);
}
3️⃣ 泛型的优势
| 特性 | 优势说明 |
|---|---|
| 类型安全 | 编译期类型检查,避免运行时错误 |
| 避免装箱/拆箱 | 提高值类型性能,减少 GC 压力 |
| 代码复用 | 一套泛型逻辑可处理多种数据类型 |
| 灵活性高 | 可定义类型约束、继承关系 |
4️⃣ 类型参数约束(where)
约束是泛型精髓,提升类型功能使用能力。
| 约束 | 说明 | 示例 |
|---|---|---|
where T : class | 引用类型 | 不能传 int |
where T : struct | 值类型 | 不能传 string |
where T : new() | 必须有无参构造函数 | 可在泛型中 new T() |
where T : BaseClass | 必须继承某类 | 可调用基类方法 |
where T : interface | 必须实现接口 | 常用于泛型算法 |
📘 约束文档:https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters
public class Factory<T> where T : new()
{
public T Create() => new T();
}
5️⃣ 泛型与集合库(泛型集合)
List<T>、Dictionary<TKey, TValue>等集合是泛型最典型应用- 强类型、高性能、支持 LINQ 操作
List<string> names = new List<string> { "Alice", "Bob" };
Dictionary<int, string> map = new Dictionary<int, string>();
📘 泛型集合汇总:https://learn.microsoft.com/en-us/dotnet/standard/collections/
6️⃣ 泛型协变与逆变(高级)
用于接口与委托场景,在泛型接口之间允许类型转换。
| 类型 | 关键字 | 用途 |
|---|---|---|
| 协变 | out | 只输出时支持子类向父类转换 |
| 逆变 | in | 只输入时支持父类向子类转换 |
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objs = strings; // 协变
📘 协变与逆变详解:https://learn.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance
7️⃣ 泛型委托
泛型委托可定义输入输出类型参数。
public delegate T Transformer<T>(T input);
Transformer<int> square = x => x * x;
.NET 内建的泛型委托:
Func<T>:有返回值Action<T>:无返回值Predicate<T>:返回布尔值
8️⃣ 泛型与反射(高级)
你可以通过反射动态创建泛型类型:
Type generic = typeof(List<>);
Type concrete = generic.MakeGenericType(typeof(string));
object instance = Activator.CreateInstance(concrete);
适合通用框架设计、插件系统等高级场景。
9️⃣ 泛型的局限性
- 泛型不支持运算符约束(如
T + T) → 可通过委托或表达式树解决 - 泛型不支持部分类型推断(复杂约束时)
- 泛型实例不能直接为
null(值类型)
🔟 实战设计模式中的泛型应用
| 模式 | 使用泛型 | 示例 |
|---|---|---|
| 仓储模式(Repository) | IRepository<T> | 统一数据访问接口 |
| 单例模式 | Singleton<T> | 泛型单例类 |
| 工厂模式 | Factory<T> | 自动创建泛型实例 |
| 服务定位器 | GetService<T>() | 动态解析依赖 |
public class Singleton<T> where T : new()
{
private static T _instance = new T();
public static T Instance => _instance;
}
泛型最佳实践
- 使用
where限定类型功能 - 不要滥用泛型,逻辑不复用时优先使用具体类型
- 结合
Func<>等泛型委托可实现函数式编程风格 - 理解协变/逆变可提升接口设计灵活性
- 使用
default(T)获取默认值(int: 0, string: null)
深入学习资源推荐
- 📘 官方泛型手册(超详细)
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/ - 📘 泛型集合结构源码参考(如 List 源码)
https://source.dot.net/ - 📘 高级泛型设计(协变/泛型工厂)
https://learn.microsoft.com/en-us/dotnet/standard/generics/
更多详细内容请关注其他相关文章!