泛型
翻译整理自 Generics 与 Type parameters。
1. 泛型类与方法
public class Stack<T>
{
private List<T> _items = new();
public void Push(T x) => _items.Add(x);
public T Pop() { var t = _items[^1]; _items.RemoveAt(_items.Count - 1); return t; }
public int Count => _items.Count;
}
var s = new Stack<int>();
s.Push(1); s.Push(2);
s.Pop();泛型方法:
public static T Max<T>(T a, T b) where T : IComparable<T>
=> a.CompareTo(b) >= 0 ? a : b;2. 类型参数约束
where T : class // 引用类型
where T : struct // 值类型
where T : new() // 有无参构造
where T : BaseClass // 继承指定基类
where T : IComparable // 实现指定接口
where T : notnull // 非空(C# 8+)
where T : unmanaged // 非托管类型
where T : U // 类型参数依赖public class Cache<T> where T : class, new()
{
public T GetOrAdd() => new();
}3. 泛型委托
public delegate T Func<T, TResult>(T arg);
// .NET 内置
Action<string> log = msg => Console.WriteLine(msg);
Func<int, int, int> add = (a, b) => a + b;4. 泛型集合
List<int> l = new() { 1, 2, 3 };
Dictionary<string, int> d = new() { ["a"] = 1 };
HashSet<int> s = new() { 1, 2, 3 };
Queue<int> q = new();
Stack<int> st = new();5. 协变逆变
IEnumerable<string> strs = new List<string>();
IEnumerable<object> objs = strs; // 协变
Action<object> printObj = o => Console.WriteLine(o);
Action<string> printStr = printObj; // 逆变6. 泛型类型推断
var x = Max(1, 2); // 推断 int
var y = Max("a", "b"); // 推断 string7. 泛型方法特化
void Print<T>(T x) { Console.WriteLine(x); }
Print<int>(1);
Print("x"); // 推断8. 泛型与反射
var listType = typeof(List<>);
var intListType = listType.MakeGenericType(typeof(int));
Console.WriteLine(intListType); // List`1[Int]9. 泛型与 LINQ
public static T[] Where<T>(this T[] source, Func<T, bool> predicate);10. 泛型类与协变
public interface IRepository<out T>
{
T Get(int id);
}
var users = new UserRepo();
IRepository<object> objs = users; // OK,out 协变小结
C# 泛型与 .NET 运行时深度集成,无装箱开销,是写出可复用、类型安全代码的核心。