泛型是 C# 中最强大的语言特性之一,基础教程中我们已经掌握了泛型的基本用法——泛型类、泛型方法、以及简单的约束。本文将深入探讨高级泛型技术,包括类型参数的协变与逆变、自定义约束的组合、静态成员与泛型、以及运行时泛型的内省机制。
协变与逆变 (out / in) 协变和逆变解决的是泛型接口/委托的类型兼容性问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public interface IProducer <out T >{ T Produce () ; } public interface IConsumer <in T >{ void Consume (T item ) ; } class Animal { }class Dog : Animal { }IProducer<Dog> dogProducer = null ; IProducer<Animal> animalProducer = dogProducer; IConsumer<Animal> animalConsumer = null ; IConsumer<Dog> dogConsumer = animalConsumer;
协变让 IEnumerable<T> 可以安全地将 IEnumerable<Dog> 赋值给 IEnumerable<Animal>,而逆变让 IComparer<Animal> 可以被当作 IComparer<Dog> 使用。
高级约束技巧 除了基础教程中的 where T : class/struct/new(),C# 支持更复杂的约束组合:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class Repository <TEntity , TKey > where TEntity : class , IEntity <TKey >, new () where TKey : struct , IEquatable <TKey > { public TEntity Create () => new TEntity(); } public class EnumParser <T > where T : struct , Enum { public static T Parse (string value ) => Enum.Parse<T>(value ); } public unsafe class Buffer <T > where T : unmanaged { public static void Copy (T* source, T* dest, int count ) { Buffer.MemoryCopy(source, dest, count * sizeof (T), count * sizeof (T)); } }
默认值关键字 1 2 3 4 5 6 public T GetOrDefault <T >(IEnumerable<T> source, int index ){ if (index >= 0 && index < source.Count()) return source.ElementAt(index); return default ; }
泛型方法中的类型推断 1 2 3 4 5 6 7 8 var result = Combine(1 , 2 ); static T Combine <T >(T a, T b ) where T : INumber<T> => a + b;static T Sum <T >(params T[] values ) where T : INumber<T> => values.Aggregate(T.Zero, (a, b) => a + b);
运行时泛型内省 1 2 3 4 5 6 7 8 9 10 11 12 class MyGenericClass <TKey , TValue > { }Type openGeneric = typeof (MyGenericClass<,>); Type closedGeneric = typeof (MyGenericClass<string , int >); Console.WriteLine(openGeneric.GetGenericArguments().Length); Console.WriteLine(closedGeneric.GetGenericArguments()[0 ]); Type runtimeType = openGeneric.MakeGenericType(typeof (int ), typeof (double )); object instance = Activator.CreateInstance(runtimeType)!;
静态成员与泛型 每个封闭泛型类型都拥有独立的静态成员副本:
1 2 3 4 5 6 7 8 9 10 class Counter <T >{ public static int Count { get ; set ; } } Counter<int >.Count = 10 ; Counter<string >.Count = 20 ; Console.WriteLine(Counter<int >.Count); Console.WriteLine(Counter<string >.Count);
这使得泛型静态字段可以用作类型到值的映射表,是实现泛型缓存模式的基石。
实战:泛型缓存模式 1 2 3 4 5 6 7 8 public static class PropertyCache <T >{ public static readonly PropertyInfo[] Properties = typeof (T).GetProperties(BindingFlags.Public | BindingFlags.Instance); } var props = PropertyCache<MyClass>.Properties;
本模式广泛应用于 ORM 框架(如 EF Core、Dapper)以及序列化库中,避免重复反射带来的性能开销。
总结 :C# 的高级泛型为类型安全带来了极大的灵活性。理解协变/逆变能让你的 API 更符合直觉,善用泛型约束可以编写更健壮的代码,而泛型缓存模式则是高性能框架设计中的经典技巧。熟练掌握这些技术,是进阶 C# 开发者的必修课。