跳至内容
张叶安的小站
用户工具
登录
站点工具
搜索
工具
显示页面
过去修订
反向链接
最近更改
媒体管理器
网站地图
登录
>
最近更改
媒体管理器
网站地图
您的足迹:
csharp:第九章泛型
本页面只读。您可以查看源文件,但不能更改它。如果您觉得这是系统错误,请联系管理员。
====== 第九章 泛型 ====== ===== 9.1 泛型基础 ===== === 为什么需要泛型 === 泛型允许我们编写类型安全、可重用的代码,而不需要在编译时确定具体类型。 <code csharp> // 不使用泛型 - 需要为每种类型写重复代码 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; } </code> ===== 9.2 泛型类 ===== === 定义泛型类 === <code csharp> 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"); </code> === 多类型参数 === <code csharp> 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"); </code> ===== 9.3 泛型方法 ===== === 定义泛型方法 === <code csharp> 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); </code> === 类中定义泛型方法 === <code csharp> 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()); </code> ===== 9.4 泛型约束 ===== === 约束类型 === | 约束 | 语法 | 说明 | |------|------|------| | 值类型 | 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必须是非空类型 | === 约束示例 === <code csharp> // 值类型约束 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必须有无参构造函数 } </code> ===== 9.5 泛型接口 ===== <code csharp> // 定义泛型接口 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 }); </code> ===== 9.6 泛型委托 ===== <code csharp> // 定义泛型委托 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; } } </code> ===== 9.7 泛型与继承 ===== <code csharp> // 泛型基类 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 </code> ===== 9.8 协变与逆变 ===== === 协变(out) === <code csharp> // 协变:可以返回更具体的类型 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; // 协变转换 </code> === 逆变(in) === <code csharp> // 逆变:可以接受更一般的类型 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; // 逆变转换 </code> ===== 9.9 实战:泛型集合类 ===== <code csharp> 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 } </code> ===== 练习题 ===== === 基础练习 === 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风格的扩展方法: - Where<T> - Select<T, TResult> - OrderBy<T, TKey> - FirstOrDefault<T> - Any<T> 8. **依赖注入容器**:实现简单的泛型DI容器: - Register<TInterface, TImplementation>() - RegisterInstance<T>(T instance) - Resolve<T>() - 支持单例和瞬态生命周期 ===== 本章小结 ===== 本章学习了C#泛型: - 泛型类和泛型方法的定义 - 多类型参数 - 泛型约束的各种类型 - 泛型接口 - 泛型委托 - 泛型与继承 - 协变和逆变 - 完整的泛型集合实现 泛型是C#类型系统的核心特性,能够大大提高代码的复用性和类型安全性。
csharp/第九章泛型.txt
· 最后更改:
2026/02/03 19:45
由
127.0.0.1
页面工具
显示页面
过去修订
反向链接
回到顶部