完整教程:C#之开放泛型和闭合泛型
在 .NET 中,“开放泛型(Open Generic)” 和 “闭合泛型(Closed Generic)” 是对泛型类型状态的两种描述,尤其常见于反射、依赖注入、插件框架等场景中。
一句话理解
- ✅ 开放泛型(Open Generic):定义了泛型参数,但还没有指定具体类型。
- ✅ 闭合泛型(Closed Generic):已经指定了所有泛型参数,成为一个完整的可用类型。
✅ 示例对比
| 类型表达式 | 类型状态 | 说明 |
|---|---|---|
List<> | 开放泛型 | 定义了类型模板,还未指定元素类型 |
List<string> | 闭合泛型 | 指定了元素类型 string |
Dictionary<,> | 开放泛型 | 有两个未指定的类型参数 |
Dictionary<int, string> | 闭合泛型 | 所有参数都已指定 |
✅ 判断方式
Type t = typeof(List<
>);
Console.WriteLine(t.IsGenericType);
// true
Console.WriteLine(t.IsGenericTypeDefinition);
// true ← 开放泛型
Type t2 = typeof(List<
int>);
Console.WriteLine(t2.IsGenericType);
// true
Console.WriteLine(t2.IsGenericTypeDefinition);
// false ← 闭合泛型
✅ 在反射中的作用
✔ 判断类型是否实现某开放泛型接口:
Type type = typeof(MyRepository);
// 假设实现了 IRepository<string>
Type openInterface = typeof(IRepository<
>);
bool implements = type.GetInterfaces()
.Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == openInterface);
✔ 动态构造闭合泛型类型
Type openGeneric = typeof(List<
>);
Type closed = openGeneric.MakeGenericType(typeof(string));
// List<string>
✅ 应用场景
| 场景 | 使用方式 |
|---|---|
| 依赖注入容器(如 Autofac) | 支持注册开放泛型,如 IRepo<> |
| 插件系统 | 加载时匹配泛型接口实现 |
| 构建表达式树 / 动态代理 | 用开放泛型定义构建闭合类型 |
| 反射分析类型关系 | 区分模板类型和已绑定类型 |
✅ 小结对比
| 特性 | 开放泛型 | 闭合泛型 |
|---|---|---|
| 是否具体可用 | ❌ 不能直接 new 或调用 | ✅ 可以直接使用 |
| 是否可构造实例 | 否 | 是 |
IsGenericType | ✅ 是 | ✅ 是 |
IsGenericTypeDefinition | ✅ 是 | ❌ 否 |
| 用途 | 模板定义、泛型比较、动态构造 | 实际使用 |
✅ 举个实战例子
假设你有一个服务接口 IHandler<T>,多个实现:
public interface IHandler<T> {
void Handle(T item);
}
public class OrderHandler
: IHandler<Order> {
...
}
public class UserHandler
: IHandler<User> {
...
}
你想通过反射找出实现了 IHandler<> 的所有类型:
Type openGeneric = typeof(IHandler<
>);
var matches = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => t.GetInterfaces()
.Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == openGeneric));

浙公网安备 33010602011771号