C#泛型底层揭秘 📅 发布时间:2026/9/2 5:48:18 👁 浏览次数: 1. 泛型本质CLR 底层视角定义泛型是类型参数化机制。在定义时不指定具体类型用占位符如T代替在实例化/调用时传入具体类型。CLR 执行时机泛型是运行时JIT真正落地的。值类型structJIT 会为每一种不同的值类型参数生成一份独立的本机代码例如Listint和Listlong是两份完全不同的机器码。引用类型classJIT 会共用一份本机代码例如Liststring、Listobject、ListStream共用同一份代码因为引用类型指针大小固定占位由运行时替换。核心性能收益避免值类型的装箱/拆箱零开销抽象同时保留编译时类型检查。2. 泛型种类语法落点泛型可以附着在5种类型上附着对象示例说明泛型类class MyClassT { }最常用类级全局占位泛型结构struct MyStructT { }值类型也能泛型化泛型接口interface IMyT { }约束行为支持协变/逆变泛型方法void MyMethodT(T arg) { }不必依赖泛型类可单独存在泛型委托delegate T MyDelegateT(T arg);如FuncT, TResult高频坑泛型方法可以存在于非泛型类中且编译器能通过参数自动推断类型不必显式写T。3. 类型约束where子句—— 面试必问约束用于限制T必须满足的条件不约束则只能使用object的方法ToString、Equals、GetHashCode。约束写法含义关键限制where T : structT 必须是值类型不可为 null不能是NullableT如int?where T : classT 必须是引用类型可以是接口、类、数组等where T : class?C# 8T 是可空引用类型主要用于可空上下文where T : notnullC# 8T 是不可空类型值或引用排除string?和int?where T : unmanagedC# 7.3T 是非托管类型不含引用常用于SpanT、内存操作、P/Invokewhere T : new()T 必须有无参构造函数必须放在约束链的最后一位where T : BaseClassT 必须是基类或派生类可调用基类成员where T : IInterfaceT 必须实现指定接口可调用接口方法where T : UT 必须继承自另一个泛型参数 U极少用解决类型关联组合约束示例含顺序csharpclass MyClassT where T : class, IComparable, new() // class在前new()必须在最后 { }4. 静态成员与泛型 —— 最大认知盲区结论泛型类的静态成员是按“闭合类型”独立存储的。MyClassint.StaticValue和MyClassstring.StaticValue是两个完全独立的静态变量互不影响。面试经典题csharpclass MyClassT { public static int Count; } MyClassint.Count 10; MyClassstring.Count 20; Console.WriteLine(MyClassint.Count); // 输出 10与string的20毫无关系原因JIT 在运行时为每个不同的闭合类型生成不同的静态字段内存区域。5. 协变out与 逆变in—— 高级多态仅适用于泛型接口和泛型委托不适用于泛型类。关键字名称作用方向示例接口允许操作out协变返回值产出IEnumerableout T允许IEnumerablestring赋给IEnumerableobjectin逆变参数消费Actionin T允许Actionobject赋给Actionstring记忆口诀out 是产出返回值in 是收入参数。重要限制协变/逆变只能用于引用类型值类型不生效IEnumerableint不能转IEnumerableobject。6.default关键字在泛型中的妙用在不知道T具体是值还是引用时用default(T)或简写default获取默认值值类型返回 0、false或空结构体。引用类型返回null。7. 泛型与反射/类型获取获取未绑定泛型开放类型typeof(MyClass)不留占位符。获取已绑定泛型闭合类型typeof(MyClassint)。运行时创建泛型实例csharpType type typeof(MyClass).MakeGenericType(typeof(string)); object obj Activator.CreateInstance(type);8. 泛型约束的局限性必须知道的坑不支持运算符重载约束无法约束T必须有或*运算符因此泛型数学运算很麻烦需借助System.Numerics.INumberT接口C# 11 .NET 7。不支持枚举约束不能写where T : enum.NET 早期限制现可用where T : struct, Enum绕行。不支持委托约束不能写where T : Delegate同样可用where T : class?绕行但无法约束具体委托类型。9. 性能特别提示面试加分项数组协变有风险object[] arr new string[10];这种写法是数组协变非泛型运行时赋值int会抛出异常。泛型集合ListT是安全的强烈替代数组协变。Listobject与Liststring不是父子关系不变性必须通过IEnumerableout T实现协变。10. 终极避坑口诀泛型版值类型泛型独立机器码零装箱。引用类型泛型共享机器码省内存。静态成员闭合成一家相互不干扰。out产出可向上子转父in收入可向下父转子。new()约束必须垫底写。default不迷茫值零引用空。