Skip to main content

泛型

泛型是什么?

泛型(Generics) 是C#中的类型参数化技术,允许编写可处理多种数据类型的代码,避免为每种类型重复编写逻辑。

核心思想:用占位符T表示类型,使用时再指定具体类型。

img

img

示例对比

// 非泛型:只能处理int类型
public class IntList {
private int[] items;
}

// 泛型:可处理任意类型
public class List<T> {
private T[] items; // T是类型占位符
}

💡 当调用List<int>时,编译器将T替换为int,生成专用类。

泛型的核心类型

(1) 泛型类

public class Box<T> {
private T _value;
public void SetValue(T value) => _value = value;
public T GetValue() => _value;
}

// 使用
var intBox = new Box<int>();
intBox.SetValue(123);

一个类可支持多种类型参数,如Dictionary<TKey, TValue>

(2) 泛型方法

public static T Max<T>(T a, T b) where T : IComparable<T> {
return a.CompareTo(b) > 0 ? a : b;
}

// 调用(类型自动推断)
int max = Max(10, 20); // T被推断为int

即使非泛型类中也可定义泛型方法。

(3) 泛型接口

public interface IRepository<T> {
void Add(T entity);
T GetById(int id);
}

public class UserRepository : IRepository<User> {
// 实现接口方法
}

接口契约可复用,实现类指定具体类型。


泛型约束

约束确保类型参数符合要求,提升安全性

img

img

示例

public class DataProcessor<T> where T : class, IEntity, new() {
public void Process() {
var obj = new T(); // 安全创建实例
obj.Id = 1; // 可访问IEntity成员
}
}

若无约束,new T()obj.Id会编译报错。


泛型核心优势

优势说明示例对比
类型安全编译时检查类型错误,避免运行时异常List<int>添加字符串会报错 vs ArrayList添加任意类型导致运行时错误
性能优化避免值类型的装箱/拆箱操作List<int>直接操作栈内存,ArrayList需装箱到堆
代码复用一套逻辑处理多种类型Max<T>方法支持int/string/double等
可读性代码意图明确,减少类型转换噪音Dictionary<string, User> vs Hashtable

实际应用场景

(1) 集合类(最常用)

List<int> numbers = new List<int>();  // 动态数组
Dictionary<string, User> userCache; // 键值对
Queue<Order> orderQueue; // 先进先出

优先使用泛型集合而非ArrayList/Hashtable

(2) 泛型缓存

public static class Cache<T> {
static Cache() {
// 每个T类型生成独立缓存
}
public static T Get(string key) { ... }
}

比字典缓存更快,因类型信息在编译时确定。

(3) 工厂模式

public class Factory<T> where T : new() {
public T Create() => new T();
}
var userFactory = new Factory<User>();
User user = userFactory.Create();

约束new()确保可实例化。

高级特性:协变与逆变

  • 协变(out):子类泛型→父类泛型(安全)
IEnumerable<Dog> dogs = new List<Dog>();
IEnumerable<Animal> animals = dogs; // 合法
  • 逆变(in):父类泛型→子类泛型(需谨慎)
Action<Animal> feedAnimal = a => a.Feed();
Action<Dog> feedDog = feedAnimal; // 合法

仅适用于接口/委托,通过out/in关键字实现。