泛型允许我们编写类型安全、可重用的代码,而不需要在编译时确定具体类型。
// 不使用泛型 - 需要为每种类型写重复代码 public class IntStack { private int[] items; public void Push(int item) { } public int Pop() => 0; } public class StringStack { private string[] items; public void Push(string item) { } public string Pop() => null; } // 使用object - 类型不安全,需要装箱拆箱 public class ObjectStack { private object[] items; public void Push(object item) { } public object Pop() => null; } // 使用泛型 - 类型安全,高性能,可重用 public class Stack<T> { private T[] items; public void Push(T item) { } public T Pop() => default; }
public class GenericClass<T> { private T value; public GenericClass(T value) { this.value = value; } public T GetValue() => value; public void SetValue(T newValue) => value = newValue; } // 使用 var intClass = new GenericClass<int>(42); var stringClass = new GenericClass<string>("Hello");
public class Pair<T1, T2> { public T1 First { get; set; } public T2 Second { get; set; } public Pair(T1 first, T2 second) { First = first; Second = second; } public void Swap() { // 只有当T1和T2相同时才能交换 // 需要使用约束或运行时检查 } public override string ToString() => $"({First}, {Second})"; } // 使用 var pair = new Pair<string, int>("Age", 25); var swapped = new Pair<int, string>(25, "Age");
public class GenericMethods { // 泛型方法 public void Swap<T>(ref T a, ref T b) { T temp = a; a = b; b = temp; } // 返回泛型类型 public T CreateInstance<T>() where T : new() { return new T(); } // 泛型参数数组 public void PrintAll<T>(params T[] items) { foreach (var item in items) { Console.WriteLine(item); } } } // 使用 var methods = new GenericMethods(); int x = 5, y = 10; methods.Swap(ref x, ref y); Console.WriteLine($"x={x}, y={y}"); methods.PrintAll("Hello", "World", "!"); methods.PrintAll(1, 2, 3, 4, 5);
public class Container<T> { private T value; // 使用类的类型参数 public void SetValue(T val) => value = val; public T GetValue() => value; // 泛型方法使用自己的类型参数 public void Process<U>(U item) { Console.WriteLine($"Container类型: {typeof(T).Name}"); Console.WriteLine($"Process类型: {typeof(U).Name}"); Console.WriteLine($"值: {item}"); } // 转换方法 public Container<U> Transform<U>(Func<T, U> converter) { return new Container<U>(converter(value)); } public Container(T value) => this.value = value; } // 使用 var container = new Container<int>(42); container.Process("测试"); // T是int, U是string var stringContainer = container.Transform(i => i.ToString());
| 约束 | 语法 | 说明 |
| —— | —— | —— |
| 值类型 | where T : struct | T必须是值类型 |
| 引用类型 | where T : class | T必须是引用类型 |
| 无参构造函数 | where T : new() | T必须有无参构造函数 |
| 基类 | where T : BaseClass | T必须继承自BaseClass |
| 接口 | where T : IInterface | T必须实现IInterface |
| 可空 | where T : notnull | T必须是非空类型 |
// 值类型约束 public class ValueTypeContainer<T> where T : struct { public T Value { get; set; } public bool HasValue => true; // 值类型总是有值 } // 引用类型约束 public class ReferenceTypeContainer<T> where T : class { private T value; public T Value { get => value; set => this.value = value ?? throw new ArgumentNullException(); } } // 构造函数约束 public class Factory<T> where T : new() { public T Create() => new T(); } // 基类约束 public class AnimalContainer<T> where T : Animal { public void MakeAllSounds(List<T> animals) { foreach (var animal in animals) { animal.MakeSound(); } } } // 接口约束 public class Sorter<T> where T : IComparable<T> { public void Sort(List<T> list) { list.Sort(); } } // 多约束 public class MultiConstraint<T> where T : class, IComparable<T>, new() { // T必须是引用类型 // T必须实现IComparable<T> // T必须有无参构造函数 }
// 定义泛型接口 public interface IRepository<T> where T : class { T GetById(int id); IEnumerable<T> GetAll(); void Add(T entity); void Update(T entity); void Delete(int id); } // 实现泛型接口 public class InMemoryRepository<T> : IRepository<T> where T : class, new() { private readonly List<T> items = new List<T>(); private int nextId = 1; public T GetById(int id) { // 假设T有Id属性 - 实际实现可能使用反射或接口约束 return items.FirstOrDefault(); } public IEnumerable<T> GetAll() => items; public void Add(T entity) { items.Add(entity); } public void Update(T entity) { // 实现更新逻辑 } public void Delete(int id) { // 实现删除逻辑 } } // 使用 public class Product { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } } var productRepo = new InMemoryRepository<Product>(); productRepo.Add(new Product { Name = "Laptop", Price = 999 });
// 定义泛型委托 public delegate TResult MyFunc<in T, out TResult>(T arg); public delegate void MyAction<in T>(T arg); public delegate bool MyPredicate<in T>(T obj); // 使用自定义泛型委托 public class GenericDelegateDemo { public static void Main() { // 使用自定义委托 MyFunc<int, string> intToString = n => $"Number: {n}"; MyAction<string> print = Console.WriteLine; MyPredicate<int> isPositive = n => n > 0; print(intToString(42)); Console.WriteLine(isPositive(5)); // 使用内置委托 Func<int, int, int> add = (a, b) => a + b; Action<string> log = msg => Console.WriteLine($"[LOG] {msg}"); Predicate<int> isEven = n => n % 2 == 0; } }
// 泛型基类 public class GenericBase<T> { public T Value { get; set; } } // 继承并指定类型 public class IntDerived : GenericBase<int> { public void Increment() => Value++; } // 保持泛型 public class GenericDerived<T> : GenericBase<T> { public void Reset() => Value = default; } // 添加类型参数 public class MultiDerived<T, U> : GenericBase<T> { public U ExtraValue { get; set; } } // 使用 var intDerived = new IntDerived { Value = 5 }; intDerived.Increment(); Console.WriteLine(intDerived.Value); // 6
// 协变:可以返回更具体的类型 public interface ICovariant<out T> { T GetItem(); // void SetItem(T item); // 编译错误,不能入参 } public class Covariant<T> : ICovariant<T> { private T item; public Covariant(T item) => this.item = item; public T GetItem() => item; } // 使用协变 ICovariant<string> stringCovariant = new Covariant<string>("Hello"); ICovariant<object> objectCovariant = stringCovariant; // 协变转换
// 逆变:可以接受更一般的类型 public interface IContravariant<in T> { void SetItem(T item); // T GetItem(); // 编译错误,不能出参 } public class Contravariant<T> : IContravariant<T> { private T item; public void SetItem(T item) => this.item = item; } // 使用逆变 IContravariant<object> objectContravariant = new Contravariant<object>(); IContravariant<string> stringContravariant = objectContravariant; // 逆变转换
public class GenericList<T> : IEnumerable<T> { private T[] items; private int count; private int capacity; public GenericList(int initialCapacity = 4) { capacity = initialCapacity; items = new T[capacity]; count = 0; } public int Count => count; public int Capacity => capacity; public T this[int index] { get { if (index < 0 || index >= count) throw new IndexOutOfRangeException(); return items[index]; } set { if (index < 0 || index >= count) throw new IndexOutOfRangeException(); items[index] = value; } } public void Add(T item) { if (count == capacity) { Grow(); } items[count++] = item; } public bool Remove(T item) { int index = IndexOf(item); if (index >= 0) { RemoveAt(index); return true; } return false; } public void RemoveAt(int index) { if (index < 0 || index >= count) throw new IndexOutOfRangeException(); for (int i = index; i < count - 1; i++) { items[i] = items[i + 1]; } count--; items[count] = default; // 清除引用 } public int IndexOf(T item) { for (int i = 0; i < count; i++) { if (EqualityComparer<T>.Default.Equals(items[i], item)) return i; } return -1; } public bool Contains(T item) => IndexOf(item) >= 0; public void Clear() { for (int i = 0; i < count; i++) { items[i] = default; } count = 0; } public void Sort() where T : IComparable<T> { Array.Sort(items, 0, count); } public void Sort(IComparer<T> comparer) { Array.Sort(items, 0, count, comparer); } private void Grow() { capacity *= 2; T[] newItems = new T[capacity]; Array.Copy(items, newItems, count); items = newItems; } public IEnumerator<T> GetEnumerator() { for (int i = 0; i < count; i++) { yield return items[i]; } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); } // 使用 var list = new GenericList<int>(); list.Add(3); list.Add(1); list.Add(2); list.Sort(); foreach (var item in list) { Console.WriteLine(item); // 1, 2, 3 }
1. 泛型交换:编写一个泛型方法Swap<T>,交换两个变量的值。
2. 泛型查找:创建泛型方法FindFirst<T>,在数组中查找第一个匹配的元素。
3. 泛型容器:实现一个简单的GenericStack<T>类,支持Push、Pop、Peek操作。
4. 泛型缓存:设计GenericCache<TKey, TValue>类:
5. 泛型比较器:实现泛型方法FindMax<T>,在集合中查找最大值,要求T实现IComparable<T>。
6. 泛型工厂:创建GenericFactory<T>,要求T必须有无参构造函数,支持对象池管理。
7. LINQ简化版:实现一组LINQ风格的扩展方法:
8. 依赖注入容器:实现简单的泛型DI容器:
本章学习了C#泛型:
泛型是C#类型系统的核心特性,能够大大提高代码的复用性和类型安全性。