十二、 泛型(Generics )

CLR #泛型

📌 一、泛型基础结构(Generic Fundamentals)

💡 本质理解:

  • CLR 泛型是 延迟绑定泛型(Open Generics),在运行时根据实际类型参数 生成真实类型

  • 每个具体类型组合(如 List<int> 和 List<string>)会 JIT 编译生成独立代码版本(值类型场景),引用类型通常共享一个代码体。

🌟 示例:

publicclassBox
{
    publicTValue;
}

🔍 IL 展开后是一个带占位符的模板类,JIT 时实例化为 Box<System.Int32> 等。

注意 根据Microsoft的设计原则,泛型参数变量要么称为 T, 要么至少以大写T开(如TKeyTValue)。大写 T代表类型(Type), 就像大写 I 代表接口(Interface)一样,比如 IComparable.


📌 二、泛型接口(Generic Interfaces)

  • 支持行为抽象 + 类型安全

  • 常用于集合(如 IEnumerable<T>IComparer<T>

publicinterfaceIRepository
{
    TGetById(intid);
}

✅ 利于解耦业务逻辑与数据模型。


📌 三、泛型委托(Generic Delegates)

  • 委托支持泛型类型参数:

publicdelegateTTransformer(Targ);

  • FCL 提供大量泛型委托:

  • Func<T>Func<T, TResult>

  • Action<T> 等


📌 四、协变 & 逆变(Covariance & Contravariance)

类型 方向 使用限制
协变 (out) 派生类 → 基类 仅用于返回类型
逆变 (in) 基类 → 派生类 仅用于参数类型

IEnumerables=newList();
IEnumerableo=s; // 协变(out)

Actiona1=x=> { };
Actiona2=a1;    // 逆变(in)

✅ CLR 在 IL 层支持泛型变体,但必须显式标记 in 或 out


📌 五、泛型方法(Generic Methods)

publicTEcho(Tinput) =>input;

  • 与泛型类无关,可作用于非泛型类中

  • 编译时推断类型,灵活性高


📌 六、泛型与其他成员

  • 泛型可以用于:

  • 属性返回值

  • 索引器

  • 事件参数等

❗ 不支持:

  • 泛型属性(不能为属性本身定义类型参数)

📌 七、泛型的约束(Constraints)

约束类型 含义
where T : class T 必须为引用类型
where T : struct T 必须为值类型
where T : new() T 必须有无参构造函数
where T : BaseType T 必须继承自指定类或接口

✅ 避免运行时 InvalidCastException,提高类型安全


📌 八、可验证性(Verifiability)

  • 泛型带来运行时类型安全保障

  • IL 检查时需确保泛型代码在 强约束下可验证

  • 不合法操作如对不确定类型的强制转换将被拒绝

✅ 示例场景:类型转换与工厂模式的泛型工具类

目标:

  • 使用泛型方法提供对象转换

  • 限制类型必须实现接口并提供无参构造函数(约束)

  • 确保操作在运行时是安全且可验证的(避免非法转换)

// 泛型约束接口
publicinterfaceIConvertibleEntity
{
    TDtoToDto();
}

// 泛型方法 + 约束 + 可验证性综合使用
publicstaticclassConverter
{
    // 泛型方法带两个约束:
    // TEntity 必须实现 IConvertibleEntity 且拥有无参构造函数
    publicstaticTDtoConvertToDto<TEntity, TDto>()
        whereTEntity : IConvertibleEntity, new()
    {
        // 符合可验证性:TEntity 有 new() 约束,构造是安全的
        TEntityentity=newTEntity();
        returnentity.ToDto();
    }
}

// 示例实体类型
publicclassProduct : IConvertibleEntity
{
    publicintId=>123;
    publicstringName=>"Laptop";

// 实现转换逻辑
    publicProductDtoToDto()
    {
        returnnewProductDto { Id=this.Id, Name=this.Name };
    }
}

// DTO 类型
publicclassProductDto
{
    publicintId { get; set; }
    publicstringName { get; set; }
}

// 使用示例
classProgram
{
    staticvoidMain()
    {
        vardto=Converter.ConvertToDto<Product, ProductDto>();
        Console.WriteLine($"{dto.Id} - {dto.Name}");
    }
}

维度 应用说明
泛型方法 ConvertToDto<TEntity, TDto>()
泛型约束 where TEntity : IConvertibleEntity<TDto>, new()
可验证性 编译器确保 TEntity 拥有无参构造函数,且支持转换
接口泛型嵌套 支持 TDto 的结构化转换
安全性 无需类型转换或反射,100%类型安全

posted @ 2025-08-26 10:06  世纪末の魔术师  阅读(19)  评论(0)    收藏  举报