【进阶】C# 泛型知识点整理归纳
一.基本概念
-
泛型(Generics):允许在定义类、接口、方法时使用类型参数,使用时指定具体类型,提升代码复用性和类型安全。
-
核心思想:延迟类型的具体化,直到使用时才明确类型
二.泛型的作用
-
类型安全:编译时检查类型,避免运行时错误(如
ArrayList
需要强制转换)。 -
性能优化:避免值类型的装箱拆箱(如
List<int>
直接操作值类型)。 -
代码复用:一套逻辑适应多种数据类型。
三.泛型默认
-
命名规范:通常以
T
开头(如TKey
,TValue
),支持多个参数(如Dictionary<TKey, TValue>
)。 -
默认值:
default(T)
根据类型返回null
(引用类型)或零值(值类型)。 -
类型推断:编译器根据参数自动推断泛型类型,简化代码。
四.泛型类型
- 泛型类:
public class MyList<T> {private T[] _items;public void Add(T item) { /* ... */ }
}
// 使用
var intList = new MyList<int>();
- 泛型接口:
public interface IRepository<T> {T GetById(int id);
}
- 泛型方法:
public void Swap<T>(ref T a, ref T b) {T temp = a;a = b;b = temp;
}
// 类型推断
int x = 1, y = 2;
Swap(ref x, ref y); // 无需显式指定<int>
五.泛型约束
- 约束(Constraints):限制类型参数的允许范围,增强类型可控性。
where T : struct // T必须是值类型
where T : class // T必须是引用类型
where T : new() // T必须有无参构造函数
where T : MyBaseClass // T必须继承自MyBaseClass
where T : IMyInterface // T必须实现IMyInterface
where T : U // T必须派生自另一个类型参数U(裸类型约束)
六.泛型与继承
- 泛型基类:派生类可继承泛型基类并指定类型参数。
public class Derived<T> : Base<T> { /* ... */ }
public class IntDerived : Base<int> { /* ... */ } // 部分关闭类型
- 静态成员:每个封闭类型(如
MyClass<int>
和MyClass<string>
)拥有独立的静态成员。
七.协变与逆变
- 协变(
out
):允许使用派生程度更高的类型(子类→父类)。
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings; // 协变
- 逆变(
in
):允许使用派生程度更低的类型(父类→子类)。
Action<object> actObject = obj => Console.WriteLine(obj);
Action<string> actString = actObject; // 逆变
- 限制:仅适用于接口和委托,且类型参数需标记
out
或in
。
八.应用场景
-
集合类:
List<T>
,Dictionary<TKey, TValue>
。 -
通用算法:如排序、比较、过滤等。
public static T Max<T>(T a, T b) where T : IComparable<T> => a.CompareTo(b) > 0 ? a : b;
- 工厂模式:创建通用对象工厂。
public class Factory<T> where T : new() {public T Create() => new T();
}
九. 高级特性
- 泛型委托:
public delegate TResult Func<T, TResult>(T arg);
- 反射与泛型:使用
MakeGenericType
动态构造泛型类型。
Type openType = typeof(List<>);
Type closedType = openType.MakeGenericType(typeof(int));
十.注意事项
-
避免过度泛型化:增加代码复杂度,需权衡可读性与灵活性。
-
运行时类型信息:C#泛型在运行时保留类型信息(与Java类型擦除不同),可通过
typeof(T)
获取。 -
合理使用约束:避免过度限制类型参数的灵活性。
十一.实例代码
// 泛型类
public class Box<T> {public T Content { get; set; }
}// 泛型方法
public static T[] CreateArray<T>(int size) where T : new() {T[] array = new T[size];for (int i = 0; i < size; i++) array[i] = new T();return array;
}// 协变与逆变示例
IEnumerable<string> strings = new List<string> { "a", "b" };
IEnumerable<object> objects = strings; // 协变Action<object> logObject = obj => Console.WriteLine(obj);
Action<string> logString = logObject; // 逆变
logString("Hello"); // 输出Hello