====== 第九章 泛型 ======
===== 9.1 泛型基础 =====
=== 为什么需要泛型 ===
泛型允许我们编写类型安全、可重用的代码,而不需要在编译时确定具体类型。
// 不使用泛型 - 需要为每种类型写重复代码
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
{
private T[] items;
public void Push(T item) { }
public T Pop() => default;
}
===== 9.2 泛型类 =====
=== 定义泛型类 ===
public class GenericClass
{
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(42);
var stringClass = new GenericClass("Hello");
=== 多类型参数 ===
public class Pair
{
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("Age", 25);
var swapped = new Pair(25, "Age");
===== 9.3 泛型方法 =====
=== 定义泛型方法 ===
public class GenericMethods
{
// 泛型方法
public void Swap(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}
// 返回泛型类型
public T CreateInstance() where T : new()
{
return new T();
}
// 泛型参数数组
public void PrintAll(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
{
private T value;
// 使用类的类型参数
public void SetValue(T val) => value = val;
public T GetValue() => value;
// 泛型方法使用自己的类型参数
public void Process(U item)
{
Console.WriteLine($"Container类型: {typeof(T).Name}");
Console.WriteLine($"Process类型: {typeof(U).Name}");
Console.WriteLine($"值: {item}");
}
// 转换方法
public Container Transform(Func converter)
{
return new Container(converter(value));
}
public Container(T value) => this.value = value;
}
// 使用
var container = new Container(42);
container.Process("测试"); // T是int, U是string
var stringContainer = container.Transform(i => i.ToString());
===== 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必须是非空类型 |
=== 约束示例 ===
// 值类型约束
public class ValueTypeContainer where T : struct
{
public T Value { get; set; }
public bool HasValue => true; // 值类型总是有值
}
// 引用类型约束
public class ReferenceTypeContainer where T : class
{
private T value;
public T Value
{
get => value;
set => this.value = value ?? throw new ArgumentNullException();
}
}
// 构造函数约束
public class Factory where T : new()
{
public T Create() => new T();
}
// 基类约束
public class AnimalContainer where T : Animal
{
public void MakeAllSounds(List animals)
{
foreach (var animal in animals)
{
animal.MakeSound();
}
}
}
// 接口约束
public class Sorter where T : IComparable
{
public void Sort(List list)
{
list.Sort();
}
}
// 多约束
public class MultiConstraint where T : class, IComparable, new()
{
// T必须是引用类型
// T必须实现IComparable
// T必须有无参构造函数
}
===== 9.5 泛型接口 =====
// 定义泛型接口
public interface IRepository where T : class
{
T GetById(int id);
IEnumerable GetAll();
void Add(T entity);
void Update(T entity);
void Delete(int id);
}
// 实现泛型接口
public class InMemoryRepository : IRepository where T : class, new()
{
private readonly List items = new List();
private int nextId = 1;
public T GetById(int id)
{
// 假设T有Id属性 - 实际实现可能使用反射或接口约束
return items.FirstOrDefault();
}
public IEnumerable 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();
productRepo.Add(new Product { Name = "Laptop", Price = 999 });
===== 9.6 泛型委托 =====
// 定义泛型委托
public delegate TResult MyFunc(T arg);
public delegate void MyAction(T arg);
public delegate bool MyPredicate(T obj);
// 使用自定义泛型委托
public class GenericDelegateDemo
{
public static void Main()
{
// 使用自定义委托
MyFunc intToString = n => $"Number: {n}";
MyAction print = Console.WriteLine;
MyPredicate isPositive = n => n > 0;
print(intToString(42));
Console.WriteLine(isPositive(5));
// 使用内置委托
Func add = (a, b) => a + b;
Action log = msg => Console.WriteLine($"[LOG] {msg}");
Predicate isEven = n => n % 2 == 0;
}
}
===== 9.7 泛型与继承 =====
// 泛型基类
public class GenericBase
{
public T Value { get; set; }
}
// 继承并指定类型
public class IntDerived : GenericBase
{
public void Increment() => Value++;
}
// 保持泛型
public class GenericDerived : GenericBase
{
public void Reset() => Value = default;
}
// 添加类型参数
public class MultiDerived : GenericBase
{
public U ExtraValue { get; set; }
}
// 使用
var intDerived = new IntDerived { Value = 5 };
intDerived.Increment();
Console.WriteLine(intDerived.Value); // 6
===== 9.8 协变与逆变 =====
=== 协变(out) ===
// 协变:可以返回更具体的类型
public interface ICovariant
{
T GetItem();
// void SetItem(T item); // 编译错误,不能入参
}
public class Covariant : ICovariant
{
private T item;
public Covariant(T item) => this.item = item;
public T GetItem() => item;
}
// 使用协变
ICovariant stringCovariant = new Covariant("Hello");
ICovariant
=== 逆变(in) ===
// 逆变:可以接受更一般的类型
public interface IContravariant
{
void SetItem(T item);
// T GetItem(); // 编译错误,不能出参
}
public class Contravariant : IContravariant
{
private T item;
public void SetItem(T item) => this.item = item;
}
// 使用逆变
IContravariant
===== 9.9 实战:泛型集合类 =====
public class GenericList : IEnumerable
{
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.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
{
Array.Sort(items, 0, count);
}
public void Sort(IComparer 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 GetEnumerator()
{
for (int i = 0; i < count; i++)
{
yield return items[i];
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
=> GetEnumerator();
}
// 使用
var list = new GenericList();
list.Add(3);
list.Add(1);
list.Add(2);
list.Sort();
foreach (var item in list)
{
Console.WriteLine(item); // 1, 2, 3
}
===== 练习题 =====
=== 基础练习 ===
1. **泛型交换**:编写一个泛型方法Swap,交换两个变量的值。
2. **泛型查找**:创建泛型方法FindFirst,在数组中查找第一个匹配的元素。
3. **泛型容器**:实现一个简单的GenericStack类,支持Push、Pop、Peek操作。
=== 进阶练习 ===
4. **泛型缓存**:设计GenericCache类:
- 支持添加、获取、删除缓存项
- 支持过期时间
- 线程安全
5. **泛型比较器**:实现泛型方法FindMax,在集合中查找最大值,要求T实现IComparable。
6. **泛型工厂**:创建GenericFactory,要求T必须有无参构造函数,支持对象池管理。
=== 挑战练习 ===
7. **LINQ简化版**:实现一组LINQ风格的扩展方法:
- Where
- Select
- OrderBy
- FirstOrDefault
- Any
8. **依赖注入容器**:实现简单的泛型DI容器:
- Register()
- RegisterInstance(T instance)
- Resolve()
- 支持单例和瞬态生命周期
===== 本章小结 =====
本章学习了C#泛型:
- 泛型类和泛型方法的定义
- 多类型参数
- 泛型约束的各种类型
- 泛型接口
- 泛型委托
- 泛型与继承
- 协变和逆变
- 完整的泛型集合实现
泛型是C#类型系统的核心特性,能够大大提高代码的复用性和类型安全性。