本章目标
通过本章学习,你将掌握: - 泛型的概念和优势 - 泛型类和泛型接口 - 泛型方法和泛型委托 - 泛型约束的使用 - 协变和逆变 - 泛型集合的使用 - 泛型的性能优势
1. 泛型基础
1.1 泛型的概念
泛型允许在定义类、接口、方法时使用类型参数,在使用时指定具体类型,提供类型安全和性能优势。
// 非泛型版本的问题
public class ObjectStack
{
private object[] items;
private int count;
public ObjectStack(int capacity = 10)
{
items = new object[capacity];
count = 0;
}
public void Push(object item)
{
if (count >= items.Length)
throw new InvalidOperationException("栈已满");
items[count++] = item;
}
public object Pop()
{
if (count == 0)
throw new InvalidOperationException("栈为空");
return items[--count];
}
public int Count => count;
}
// 泛型版本的优势
public class GenericStack<T>
{
private T[] items;
private int count;
public GenericStack(int capacity = 10)
{
items = new T[capacity];
count = 0;
}
public void Push(T item)
{
if (count >= items.Length)
{
// 自动扩容
Array.Resize(ref items, items.Length * 2);
}
items[count++] = item;
}
public T Pop()
{
if (count == 0)
throw new InvalidOperationException("栈为空");
return items[--count];
}
public T Peek()
{
if (count == 0)
throw new InvalidOperationException("栈为空");
return items[count - 1];
}
public bool IsEmpty => count == 0;
public int Count => count;
public int Capacity => items.Length;
// 泛型方法
public bool Contains(T item)
{
for (int i = 0; i < count; i++)
{
if (EqualityComparer<T>.Default.Equals(items[i], item))
return true;
}
return false;
}
public T[] ToArray()
{
T[] result = new T[count];
Array.Copy(items, result, count);
return result;
}
public void Clear()
{
// 对于引用类型,清除引用以便垃圾回收
if (!typeof(T).IsValueType)
{
Array.Clear(items, 0, count);
}
count = 0;
}
}
// 泛型使用示例
public class GenericBasicsDemo
{
public static void DemonstrateGenericAdvantages()
{
Console.WriteLine("=== 泛型优势演示 ===");
// 非泛型版本的问题
Console.WriteLine("\n--- 非泛型版本的问题 ---");
var objectStack = new ObjectStack();
objectStack.Push(1); // 装箱
objectStack.Push("hello"); // 类型不安全
objectStack.Push(3.14); // 装箱
// 需要类型转换,可能出现运行时错误
try
{
int value1 = (int)objectStack.Pop(); // 拆箱
Console.WriteLine($"弹出:{value1}");
int value2 = (int)objectStack.Pop(); // 运行时错误!
Console.WriteLine($"弹出:{value2}");
}
catch (InvalidCastException ex)
{
Console.WriteLine($"类型转换错误:{ex.Message}");
}
// 泛型版本的优势
Console.WriteLine("\n--- 泛型版本的优势 ---");
var intStack = new GenericStack<int>();
intStack.Push(1); // 无装箱
intStack.Push(2); // 类型安全
intStack.Push(3);
Console.WriteLine($"栈中元素数量:{intStack.Count}");
Console.WriteLine($"栈容量:{intStack.Capacity}");
Console.WriteLine($"栈顶元素:{intStack.Peek()}");
while (!intStack.IsEmpty)
{
int value = intStack.Pop(); // 无需类型转换
Console.WriteLine($"弹出:{value}");
}
// 字符串栈
var stringStack = new GenericStack<string>();
stringStack.Push("Hello");
stringStack.Push("World");
stringStack.Push("Generic");
Console.WriteLine($"\n字符串栈包含'World':{stringStack.Contains("World")}");
Console.WriteLine($"字符串栈内容:[{string.Join(", ", stringStack.ToArray())}]");
// 自定义类型栈
var personStack = new GenericStack<Person>();
personStack.Push(new Person("张三", 25));
personStack.Push(new Person("李四", 30));
Console.WriteLine($"\n人员栈顶:{personStack.Peek()}");
}
}
// 示例类
public class Person
{
public string Name { get; }
public int Age { get; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
public override string ToString()
{
return $"{Name}({Age}岁)";
}
public override bool Equals(object obj)
{
return obj is Person person && Name == person.Name && Age == person.Age;
}
public override int GetHashCode()
{
return HashCode.Combine(Name, Age);
}
}
1.2 泛型类和泛型接口
// 泛型接口
public interface IRepository<T> where T : class
{
void Add(T entity);
T GetById(int id);
IEnumerable<T> GetAll();
void Update(T entity);
void Delete(int id);
bool Exists(int id);
}
// 泛型基类
public abstract class BaseEntity
{
public int Id { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
protected BaseEntity()
{
CreatedAt = DateTime.Now;
UpdatedAt = DateTime.Now;
}
}
// 具体实体类
public class Product : BaseEntity
{
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
public int Stock { get; set; }
public Product() { }
public Product(string name, decimal price, string category, int stock)
{
Name = name;
Price = price;
Category = category;
Stock = stock;
}
public override string ToString()
{
return $"{Name} - ¥{Price} ({Category}) [库存:{Stock}]";
}
}
public class Customer : BaseEntity
{
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Address { get; set; }
public Customer() { }
public Customer(string name, string email, string phone, string address)
{
Name = name;
Email = email;
Phone = phone;
Address = address;
}
public override string ToString()
{
return $"{Name} ({Email}) - {Phone}";
}
}
// 泛型仓储实现
public class MemoryRepository<T> : IRepository<T> where T : BaseEntity
{
private readonly Dictionary<int, T> entities;
private int nextId;
public MemoryRepository()
{
entities = new Dictionary<int, T>();
nextId = 1;
}
public void Add(T entity)
{
if (entity == null)
throw new ArgumentNullException(nameof(entity));
entity.Id = nextId++;
entity.CreatedAt = DateTime.Now;
entity.UpdatedAt = DateTime.Now;
entities[entity.Id] = entity;
Console.WriteLine($"添加实体:{entity.GetType().Name} (ID: {entity.Id})");
}
public T GetById(int id)
{
entities.TryGetValue(id, out T entity);
return entity;
}
public IEnumerable<T> GetAll()
{
return entities.Values.OrderBy(e => e.Id);
}
public void Update(T entity)
{
if (entity == null)
throw new ArgumentNullException(nameof(entity));
if (!entities.ContainsKey(entity.Id))
throw new ArgumentException($"实体不存在:ID {entity.Id}");
entity.UpdatedAt = DateTime.Now;
entities[entity.Id] = entity;
Console.WriteLine($"更新实体:{entity.GetType().Name} (ID: {entity.Id})");
}
public void Delete(int id)
{
if (entities.Remove(id))
{
Console.WriteLine($"删除实体:ID {id}");
}
else
{
throw new ArgumentException($"实体不存在:ID {id}");
}
}
public bool Exists(int id)
{
return entities.ContainsKey(id);
}
public int Count => entities.Count;
// 额外的泛型方法
public IEnumerable<T> FindBy(Func<T, bool> predicate)
{
return entities.Values.Where(predicate);
}
public T FirstOrDefault(Func<T, bool> predicate)
{
return entities.Values.FirstOrDefault(predicate);
}
}
// 泛型服务类
public class GenericService<T> where T : BaseEntity
{
private readonly IRepository<T> repository;
public GenericService(IRepository<T> repository)
{
this.repository = repository ?? throw new ArgumentNullException(nameof(repository));
}
public void CreateEntity(T entity)
{
ValidateEntity(entity);
repository.Add(entity);
}
public T GetEntity(int id)
{
var entity = repository.GetById(id);
if (entity == null)
throw new ArgumentException($"实体不存在:ID {id}");
return entity;
}
public IEnumerable<T> GetAllEntities()
{
return repository.GetAll();
}
public void UpdateEntity(T entity)
{
ValidateEntity(entity);
repository.Update(entity);
}
public void DeleteEntity(int id)
{
repository.Delete(id);
}
public bool EntityExists(int id)
{
return repository.Exists(id);
}
protected virtual void ValidateEntity(T entity)
{
if (entity == null)
throw new ArgumentNullException(nameof(entity));
}
// 泛型查询方法
public IEnumerable<T> Search(Func<T, bool> criteria)
{
return repository.FindBy(criteria);
}
public T FindFirst(Func<T, bool> criteria)
{
return repository.FirstOrDefault(criteria);
}
}
// 具体服务类
public class ProductService : GenericService<Product>
{
public ProductService(IRepository<Product> repository) : base(repository) { }
protected override void ValidateEntity(Product product)
{
base.ValidateEntity(product);
if (string.IsNullOrWhiteSpace(product.Name))
throw new ArgumentException("产品名称不能为空");
if (product.Price <= 0)
throw new ArgumentException("产品价格必须大于0");
if (product.Stock < 0)
throw new ArgumentException("库存不能为负数");
}
public IEnumerable<Product> GetProductsByCategory(string category)
{
return Search(p => p.Category.Equals(category, StringComparison.OrdinalIgnoreCase));
}
public IEnumerable<Product> GetProductsInPriceRange(decimal minPrice, decimal maxPrice)
{
return Search(p => p.Price >= minPrice && p.Price <= maxPrice);
}
public IEnumerable<Product> GetLowStockProducts(int threshold = 10)
{
return Search(p => p.Stock <= threshold);
}
}
public class CustomerService : GenericService<Customer>
{
public CustomerService(IRepository<Customer> repository) : base(repository) { }
protected override void ValidateEntity(Customer customer)
{
base.ValidateEntity(customer);
if (string.IsNullOrWhiteSpace(customer.Name))
throw new ArgumentException("客户姓名不能为空");
if (string.IsNullOrWhiteSpace(customer.Email) || !customer.Email.Contains("@"))
throw new ArgumentException("邮箱格式无效");
}
public Customer GetCustomerByEmail(string email)
{
return FindFirst(c => c.Email.Equals(email, StringComparison.OrdinalIgnoreCase));
}
public IEnumerable<Customer> SearchCustomersByName(string namePattern)
{
return Search(c => c.Name.Contains(namePattern, StringComparison.OrdinalIgnoreCase));
}
}
1.3 泛型类和接口使用示例
public class GenericClassDemo
{
public static void DemonstrateGenericClasses()
{
Console.WriteLine("\n=== 泛型类和接口演示 ===");
// 创建仓储和服务
var productRepository = new MemoryRepository<Product>();
var customerRepository = new MemoryRepository<Customer>();
var productService = new ProductService(productRepository);
var customerService = new CustomerService(customerRepository);
// 添加产品
Console.WriteLine("\n--- 添加产品 ---");
productService.CreateEntity(new Product("笔记本电脑", 5999.99m, "电子产品", 50));
productService.CreateEntity(new Product("无线鼠标", 199.99m, "电子产品", 100));
productService.CreateEntity(new Product("机械键盘", 599.99m, "电子产品", 30));
productService.CreateEntity(new Product("办公椅", 899.99m, "家具", 20));
productService.CreateEntity(new Product("台灯", 299.99m, "家具", 5));
// 添加客户
Console.WriteLine("\n--- 添加客户 ---");
customerService.CreateEntity(new Customer("张三", "zhangsan@email.com", "13800138000", "北京市朝阳区"));
customerService.CreateEntity(new Customer("李四", "lisi@email.com", "13900139000", "上海市浦东新区"));
customerService.CreateEntity(new Customer("王五", "wangwu@email.com", "13700137000", "广州市天河区"));
// 查询产品
Console.WriteLine("\n--- 产品查询 ---");
var allProducts = productService.GetAllEntities();
Console.WriteLine($"所有产品 ({allProducts.Count()}个):");
foreach (var product in allProducts)
{
Console.WriteLine($" {product}");
}
var electronicProducts = productService.GetProductsByCategory("电子产品");
Console.WriteLine($"\n电子产品 ({electronicProducts.Count()}个):");
foreach (var product in electronicProducts)
{
Console.WriteLine($" {product}");
}
var affordableProducts = productService.GetProductsInPriceRange(100, 600);
Console.WriteLine($"\n价格在100-600元的产品 ({affordableProducts.Count()}个):");
foreach (var product in affordableProducts)
{
Console.WriteLine($" {product}");
}
var lowStockProducts = productService.GetLowStockProducts(25);
Console.WriteLine($"\n低库存产品 (≤25件) ({lowStockProducts.Count()}个):");
foreach (var product in lowStockProducts)
{
Console.WriteLine($" {product}");
}
// 查询客户
Console.WriteLine("\n--- 客户查询 ---");
var allCustomers = customerService.GetAllEntities();
Console.WriteLine($"所有客户 ({allCustomers.Count()}个):");
foreach (var customer in allCustomers)
{
Console.WriteLine($" {customer}");
}
var customer = customerService.GetCustomerByEmail("lisi@email.com");
Console.WriteLine($"\n邮箱为lisi@email.com的客户:{customer}");
var customersWithWang = customerService.SearchCustomersByName("王");
Console.WriteLine($"\n姓名包含'王'的客户 ({customersWithWang.Count()}个):");
foreach (var c in customersWithWang)
{
Console.WriteLine($" {c}");
}
// 更新和删除
Console.WriteLine("\n--- 更新和删除操作 ---");
var productToUpdate = productService.GetEntity(1);
productToUpdate.Price = 5499.99m;
productToUpdate.Stock = 45;
productService.UpdateEntity(productToUpdate);
Console.WriteLine($"更新后的产品:{productToUpdate}");
productService.DeleteEntity(5);
Console.WriteLine($"删除产品后,剩余产品数量:{productService.GetAllEntities().Count()}");
}
}
2. 泛型方法和泛型委托
2.1 泛型方法
public static class GenericMethods
{
// 基本泛型方法
public static void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}
// 泛型方法重载
public static T Max<T>(T a, T b) where T : IComparable<T>
{
return a.CompareTo(b) >= 0 ? a : b;
}
public static T Max<T>(params T[] values) where T : IComparable<T>
{
if (values == null || values.Length == 0)
throw new ArgumentException("至少需要一个值");
T max = values[0];
for (int i = 1; i < values.Length; i++)
{
if (values[i].CompareTo(max) > 0)
max = values[i];
}
return max;
}
// 泛型搜索方法
public static int BinarySearch<T>(T[] array, T target) where T : IComparable<T>
{
if (array == null)
throw new ArgumentNullException(nameof(array));
int left = 0;
int right = array.Length - 1;
while (left <= right)
{
int mid = left + (right - left) / 2;
int comparison = array[mid].CompareTo(target);
if (comparison == 0)
return mid;
else if (comparison < 0)
left = mid + 1;
else
right = mid - 1;
}
return -1; // 未找到
}
// 泛型排序方法
public static void QuickSort<T>(T[] array, int low = 0, int high = -1) where T : IComparable<T>
{
if (array == null)
throw new ArgumentNullException(nameof(array));
if (high == -1)
high = array.Length - 1;
if (low < high)
{
int pivotIndex = Partition(array, low, high);
QuickSort(array, low, pivotIndex - 1);
QuickSort(array, pivotIndex + 1, high);
}
}
private static int Partition<T>(T[] array, int low, int high) where T : IComparable<T>
{
T pivot = array[high];
int i = low - 1;
for (int j = low; j < high; j++)
{
if (array[j].CompareTo(pivot) <= 0)
{
i++;
Swap(ref array[i], ref array[j]);
}
}
Swap(ref array[i + 1], ref array[high]);
return i + 1;
}
// 泛型转换方法
public static TOutput[] ConvertArray<TInput, TOutput>(TInput[] input, Func<TInput, TOutput> converter)
{
if (input == null)
throw new ArgumentNullException(nameof(input));
if (converter == null)
throw new ArgumentNullException(nameof(converter));
TOutput[] output = new TOutput[input.Length];
for (int i = 0; i < input.Length; i++)
{
output[i] = converter(input[i]);
}
return output;
}
// 泛型过滤方法
public static T[] Filter<T>(T[] array, Func<T, bool> predicate)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
if (predicate == null)
throw new ArgumentNullException(nameof(predicate));
var result = new List<T>();
foreach (T item in array)
{
if (predicate(item))
result.Add(item);
}
return result.ToArray();
}
// 泛型聚合方法
public static TResult Aggregate<T, TResult>(IEnumerable<T> source, TResult seed, Func<TResult, T, TResult> func)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (func == null)
throw new ArgumentNullException(nameof(func));
TResult result = seed;
foreach (T item in source)
{
result = func(result, item);
}
return result;
}
// 泛型缓存方法
private static readonly Dictionary<string, object> cache = new Dictionary<string, object>();
public static T GetOrCreate<T>(string key, Func<T> factory)
{
if (cache.TryGetValue(key, out object value))
{
return (T)value;
}
T newValue = factory();
cache[key] = newValue;
return newValue;
}
// 泛型单例方法
public static T CreateSingleton<T>() where T : new()
{
return SingletonHelper<T>.Instance;
}
private static class SingletonHelper<T> where T : new()
{
public static readonly T Instance = new T();
}
}
// 泛型方法使用示例
public class GenericMethodsDemo
{
public static void DemonstrateGenericMethods()
{
Console.WriteLine("\n=== 泛型方法演示 ===");
// 交换方法
Console.WriteLine("\n--- 交换方法 ---");
int a = 10, b = 20;
Console.WriteLine($"交换前:a = {a}, b = {b}");
GenericMethods.Swap(ref a, ref b);
Console.WriteLine($"交换后:a = {a}, b = {b}");
string str1 = "Hello", str2 = "World";
Console.WriteLine($"交换前:str1 = {str1}, str2 = {str2}");
GenericMethods.Swap(ref str1, ref str2);
Console.WriteLine($"交换后:str1 = {str1}, str2 = {str2}");
// 最大值方法
Console.WriteLine("\n--- 最大值方法 ---");
Console.WriteLine($"Max(10, 20) = {GenericMethods.Max(10, 20)}");
Console.WriteLine($"Max(3.14, 2.71) = {GenericMethods.Max(3.14, 2.71)}");
Console.WriteLine($"Max('A', 'Z') = {GenericMethods.Max('A', 'Z')}");
Console.WriteLine($"Max(1, 5, 3, 9, 2) = {GenericMethods.Max(1, 5, 3, 9, 2)}");
// 排序和搜索
Console.WriteLine("\n--- 排序和搜索 ---");
int[] numbers = { 64, 34, 25, 12, 22, 11, 90 };
Console.WriteLine($"排序前:[{string.Join(", ", numbers)}]");
GenericMethods.QuickSort(numbers);
Console.WriteLine($"排序后:[{string.Join(", ", numbers)}]");
int target = 25;
int index = GenericMethods.BinarySearch(numbers, target);
Console.WriteLine($"搜索 {target}:索引 = {index}");
// 数组转换
Console.WriteLine("\n--- 数组转换 ---");
string[] stringNumbers = { "1", "2", "3", "4", "5" };
int[] convertedNumbers = GenericMethods.ConvertArray(stringNumbers, int.Parse);
Console.WriteLine($"字符串数组:[{string.Join(", ", stringNumbers)}]");
Console.WriteLine($"转换为整数:[{string.Join(", ", convertedNumbers)}]");
// 数组过滤
Console.WriteLine("\n--- 数组过滤 ---");
int[] allNumbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int[] evenNumbers = GenericMethods.Filter(allNumbers, n => n % 2 == 0);
Console.WriteLine($"所有数字:[{string.Join(", ", allNumbers)}]");
Console.WriteLine($"偶数:[{string.Join(", ", evenNumbers)}]");
// 聚合操作
Console.WriteLine("\n--- 聚合操作 ---");
int sum = GenericMethods.Aggregate(allNumbers, 0, (acc, n) => acc + n);
string concatenated = GenericMethods.Aggregate(stringNumbers, "", (acc, s) => acc + s);
Console.WriteLine($"数字求和:{sum}");
Console.WriteLine($"字符串连接:{concatenated}");
// 缓存和单例
Console.WriteLine("\n--- 缓存和单例 ---");
var list1 = GenericMethods.GetOrCreate("myList", () => new List<int> { 1, 2, 3 });
var list2 = GenericMethods.GetOrCreate("myList", () => new List<int> { 4, 5, 6 });
Console.WriteLine($"缓存测试 - 相同实例:{ReferenceEquals(list1, list2)}");
var singleton1 = GenericMethods.CreateSingleton<StringBuilder>();
var singleton2 = GenericMethods.CreateSingleton<StringBuilder>();
Console.WriteLine($"单例测试 - 相同实例:{ReferenceEquals(singleton1, singleton2)}");
}
}
2.2 泛型委托
// 自定义泛型委托
public delegate T GenericFunc<T>();
public delegate T GenericFunc<T, U>(U input);
public delegate void GenericAction<T>(T input);
public delegate bool GenericPredicate<T>(T input);
public delegate int GenericComparison<T>(T x, T y);
// 泛型事件处理
public class GenericEventArgs<T> : EventArgs
{
public T Data { get; }
public DateTime Timestamp { get; }
public GenericEventArgs(T data)
{
Data = data;
Timestamp = DateTime.Now;
}
}
public delegate void GenericEventHandler<T>(object sender, GenericEventArgs<T> e);
// 泛型观察者模式
public class GenericObservable<T>
{
private readonly List<Action<T>> observers = new List<Action<T>>();
public event GenericEventHandler<T> DataChanged;
public void Subscribe(Action<T> observer)
{
if (observer != null && !observers.Contains(observer))
{
observers.Add(observer);
}
}
public void Unsubscribe(Action<T> observer)
{
observers.Remove(observer);
}
public void Notify(T data)
{
// 通知所有观察者
foreach (var observer in observers.ToList())
{
try
{
observer(data);
}
catch (Exception ex)
{
Console.WriteLine($"观察者通知失败:{ex.Message}");
}
}
// 触发事件
DataChanged?.Invoke(this, new GenericEventArgs<T>(data));
}
public int ObserverCount => observers.Count;
}
// 泛型命令模式
public interface IGenericCommand<T>
{
void Execute(T parameter);
bool CanExecute(T parameter);
}
public class GenericCommand<T> : IGenericCommand<T>
{
private readonly Action<T> executeAction;
private readonly Func<T, bool> canExecuteFunc;
public GenericCommand(Action<T> executeAction, Func<T, bool> canExecuteFunc = null)
{
this.executeAction = executeAction ?? throw new ArgumentNullException(nameof(executeAction));
this.canExecuteFunc = canExecuteFunc;
}
public void Execute(T parameter)
{
if (CanExecute(parameter))
{
executeAction(parameter);
}
else
{
throw new InvalidOperationException("命令无法执行");
}
}
public bool CanExecute(T parameter)
{
return canExecuteFunc?.Invoke(parameter) ?? true;
}
}
// 泛型工厂模式
public class GenericFactory<T>
{
private readonly Dictionary<string, Func<T>> factories = new Dictionary<string, Func<T>>();
public void Register(string key, Func<T> factory)
{
if (string.IsNullOrEmpty(key))
throw new ArgumentException("键不能为空", nameof(key));
if (factory == null)
throw new ArgumentNullException(nameof(factory));
factories[key] = factory;
}
public T Create(string key)
{
if (factories.TryGetValue(key, out Func<T> factory))
{
return factory();
}
throw new ArgumentException($"未找到工厂:{key}");
}
public bool IsRegistered(string key)
{
return factories.ContainsKey(key);
}
public IEnumerable<string> GetRegisteredKeys()
{
return factories.Keys;
}
}
// 泛型委托使用示例
public class GenericDelegateDemo
{
public static void DemonstrateGenericDelegates()
{
Console.WriteLine("\n=== 泛型委托演示 ===");
// 基本泛型委托
Console.WriteLine("\n--- 基本泛型委托 ---");
GenericFunc<string> stringFactory = () => $"生成的字符串 {DateTime.Now:HH:mm:ss}";
GenericFunc<int, string> intToString = x => $"数字:{x}";
GenericAction<string> stringPrinter = s => Console.WriteLine($"打印:{s}");
GenericPredicate<int> isEven = x => x % 2 == 0;
string generatedString = stringFactory();
stringPrinter(generatedString);
stringPrinter(intToString(42));
Console.WriteLine($"42是偶数:{isEven(42)}");
Console.WriteLine($"43是偶数:{isEven(43)}");
// 泛型观察者模式
Console.WriteLine("\n--- 泛型观察者模式 ---");
var observable = new GenericObservable<string>();
// 订阅观察者
observable.Subscribe(data => Console.WriteLine($"观察者1收到:{data}"));
observable.Subscribe(data => Console.WriteLine($"观察者2收到:{data.ToUpper()}"));
// 订阅事件
observable.DataChanged += (sender, e) =>
Console.WriteLine($"事件处理:{e.Data} (时间:{e.Timestamp:HH:mm:ss})");
Console.WriteLine($"当前观察者数量:{observable.ObserverCount}");
// 通知观察者
observable.Notify("Hello World");
observable.Notify("Generic Programming");
// 泛型命令模式
Console.WriteLine("\n--- 泛型命令模式 ---");
var printCommand = new GenericCommand<string>(
text => Console.WriteLine($"执行命令:{text}"),
text => !string.IsNullOrEmpty(text)
);
var mathCommand = new GenericCommand<int>(
number => Console.WriteLine($"计算结果:{number * number}"),
number => number >= 0
);
try
{
printCommand.Execute("Hello Command");
mathCommand.Execute(5);
// 这会失败
printCommand.Execute("");
}
catch (InvalidOperationException ex)
{
Console.WriteLine($"命令执行失败:{ex.Message}");
}
// 泛型工厂模式
Console.WriteLine("\n--- 泛型工厂模式 ---");
var stringFactory2 = new GenericFactory<string>();
stringFactory2.Register("greeting", () => "Hello, World!");
stringFactory2.Register("timestamp", () => DateTime.Now.ToString());
stringFactory2.Register("guid", () => Guid.NewGuid().ToString());
Console.WriteLine($"注册的工厂:[{string.Join(", ", stringFactory2.GetRegisteredKeys())}]");
foreach (string key in stringFactory2.GetRegisteredKeys())
{
string value = stringFactory2.Create(key);
Console.WriteLine($"{key}: {value}");
}
// 数字工厂
var numberFactory = new GenericFactory<int>();
numberFactory.Register("random", () => new Random().Next(1, 100));
numberFactory.Register("timestamp", () => (int)DateTimeOffset.Now.ToUnixTimeSeconds());
numberFactory.Register("constant", () => 42);
Console.WriteLine("\n数字工厂:");
foreach (string key in numberFactory.GetRegisteredKeys())
{
int value = numberFactory.Create(key);
Console.WriteLine($"{key}: {value}");
}
}
}
3. 泛型约束
3.1 约束类型
// where T : class - 引用类型约束
public class ReferenceTypeContainer<T> where T : class
{
private T item;
public T Item
{
get => item;
set => item = value; // 可以为null
}
public bool IsNull => item == null;
public void SetToNull()
{
item = null; // 引用类型可以设置为null
}
}
// where T : struct - 值类型约束
public class ValueTypeContainer<T> where T : struct
{
private T item;
private bool hasValue;
public T Item
{
get => hasValue ? item : throw new InvalidOperationException("没有值");
set
{
item = value;
hasValue = true;
}
}
public bool HasValue => hasValue;
public T GetValueOrDefault(T defaultValue = default)
{
return hasValue ? item : defaultValue;
}
public void Clear()
{
item = default;
hasValue = false;
}
}
// where T : new() - 无参构造函数约束
public class Factory<T> where T : new()
{
public T CreateInstance()
{
return new T();
}
public T[] CreateArray(int count)
{
T[] array = new T[count];
for (int i = 0; i < count; i++)
{
array[i] = new T();
}
return array;
}
public List<T> CreateList(int count)
{
var list = new List<T>();
for (int i = 0; i < count; i++)
{
list.Add(new T());
}
return list;
}
}
// where T : BaseClass - 基类约束
public abstract class Shape
{
public abstract double Area { get; }
public abstract double Perimeter { get; }
public abstract string Name { get; }
public virtual void Draw()
{
Console.WriteLine($"绘制{Name}");
}
}
public class Circle : Shape
{
public double Radius { get; set; }
public Circle() { }
public Circle(double radius) => Radius = radius;
public override double Area => Math.PI * Radius * Radius;
public override double Perimeter => 2 * Math.PI * Radius;
public override string Name => "圆形";
}
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
public Rectangle() { }
public Rectangle(double width, double height)
{
Width = width;
Height = height;
}
public override double Area => Width * Height;
public override double Perimeter => 2 * (Width + Height);
public override string Name => "矩形";
}
public class ShapeContainer<T> where T : Shape, new()
{
private List<T> shapes = new List<T>();
public void AddShape(T shape)
{
shapes.Add(shape);
}
public T CreateAndAddShape()
{
T shape = new T();
shapes.Add(shape);
return shape;
}
public double TotalArea => shapes.Sum(s => s.Area);
public double TotalPerimeter => shapes.Sum(s => s.Perimeter);
public int Count => shapes.Count;
public void DrawAll()
{
foreach (T shape in shapes)
{
shape.Draw();
}
}
public IEnumerable<T> GetShapes() => shapes.AsReadOnly();
}
// where T : IInterface - 接口约束
public interface IComparable<T>
{
int CompareTo(T other);
}
public interface ICloneable<T>
{
T Clone();
}
public class SortedContainer<T> where T : IComparable<T>
{
private List<T> items = new List<T>();
public void Add(T item)
{
int index = items.BinarySearch(item);
if (index < 0)
index = ~index;
items.Insert(index, item);
}
public bool Remove(T item)
{
return items.Remove(item);
}
public T this[int index] => items[index];
public int Count => items.Count;
public bool Contains(T item)
{
return items.BinarySearch(item) >= 0;
}
public IEnumerable<T> GetItems() => items.AsReadOnly();
}
// 多重约束
public class CloneableRepository<T> where T : class, ICloneable<T>, new()
{
private List<T> items = new List<T>();
public void Add(T item)
{
items.Add(item);
}
public T GetCopy(int index)
{
if (index < 0 || index >= items.Count)
throw new ArgumentOutOfRangeException(nameof(index));
return items[index].Clone();
}
public List<T> GetAllCopies()
{
return items.Select(item => item.Clone()).ToList();
}
public T CreateNew()
{
return new T();
}
public int Count => items.Count;
}
// 示例可克隆类
public class Person : ICloneable<Person>, IComparable<Person>
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
public Person() { }
public Person(string name, int age, string email)
{
Name = name;
Age = age;
Email = email;
}
public Person Clone()
{
return new Person(Name, Age, Email);
}
public int CompareTo(Person other)
{
if (other == null) return 1;
int nameComparison = string.Compare(Name, other.Name, StringComparison.OrdinalIgnoreCase);
if (nameComparison != 0) return nameComparison;
return Age.CompareTo(other.Age);
}
public override string ToString()
{
return $"{Name}({Age}岁) - {Email}";
}
public override bool Equals(object obj)
{
return obj is Person person && Name == person.Name && Age == person.Age;
}
public override int GetHashCode()
{
return HashCode.Combine(Name, Age);
}
}
3.2 泛型约束使用示例
public class GenericConstraintsDemo
{
public static void DemonstrateGenericConstraints()
{
Console.WriteLine("\n=== 泛型约束演示 ===");
// 引用类型约束
Console.WriteLine("\n--- 引用类型约束 ---");
var stringContainer = new ReferenceTypeContainer<string>();
stringContainer.Item = "Hello World";
Console.WriteLine($"字符串容器:{stringContainer.Item}");
Console.WriteLine($"是否为null:{stringContainer.IsNull}");
stringContainer.SetToNull();
Console.WriteLine($"设置为null后:{stringContainer.IsNull}");
var personContainer = new ReferenceTypeContainer<Person>();
personContainer.Item = new Person("张三", 25, "zhangsan@email.com");
Console.WriteLine($"人员容器:{personContainer.Item}");
// 值类型约束
Console.WriteLine("\n--- 值类型约束 ---");
var intContainer = new ValueTypeContainer<int>();
Console.WriteLine($"初始状态有值:{intContainer.HasValue}");
Console.WriteLine($"默认值:{intContainer.GetValueOrDefault(999)}");
intContainer.Item = 42;
Console.WriteLine($"设置值后:{intContainer.Item}");
Console.WriteLine($"现在有值:{intContainer.HasValue}");
var dateTimeContainer = new ValueTypeContainer<DateTime>();
dateTimeContainer.Item = DateTime.Now;
Console.WriteLine($"日期时间容器:{dateTimeContainer.Item}");
// 无参构造函数约束
Console.WriteLine("\n--- 无参构造函数约束 ---");
var personFactory = new Factory<Person>();
Person newPerson = personFactory.CreateInstance();
Console.WriteLine($"创建的新人员:{newPerson}");
Person[] personArray = personFactory.CreateArray(3);
Console.WriteLine($"创建的人员数组长度:{personArray.Length}");
List<Person> personList = personFactory.CreateList(2);
Console.WriteLine($"创建的人员列表数量:{personList.Count}");
// 基类约束
Console.WriteLine("\n--- 基类约束 ---");
var circleContainer = new ShapeContainer<Circle>();
circleContainer.CreateAndAddShape();
var circle = new Circle(5.0);
circleContainer.AddShape(circle);
Console.WriteLine($"圆形容器中的形状数量:{circleContainer.Count}");
Console.WriteLine($"总面积:{circleContainer.TotalArea:F2}");
Console.WriteLine($"总周长:{circleContainer.TotalPerimeter:F2}");
Console.WriteLine("绘制所有圆形:");
circleContainer.DrawAll();
// 接口约束
Console.WriteLine("\n--- 接口约束 ---");
var sortedPersons = new SortedContainer<Person>();
sortedPersons.Add(new Person("张三", 25, "zhangsan@email.com"));
sortedPersons.Add(new Person("李四", 30, "lisi@email.com"));
sortedPersons.Add(new Person("王五", 20, "wangwu@email.com"));
sortedPersons.Add(new Person("张三", 22, "zhangsan2@email.com")); // 同名但年龄不同
Console.WriteLine($"排序后的人员 ({sortedPersons.Count}个):");
foreach (Person person in sortedPersons.GetItems())
{
Console.WriteLine($" {person}");
}
Console.WriteLine($"包含'李四(30岁)':{sortedPersons.Contains(new Person("李四", 30, "lisi@email.com"))}");
// 多重约束
Console.WriteLine("\n--- 多重约束 ---");
var cloneableRepo = new CloneableRepository<Person>();
cloneableRepo.Add(new Person("原始张三", 25, "original@email.com"));
cloneableRepo.Add(new Person("原始李四", 30, "original2@email.com"));
Console.WriteLine($"仓库中的人员数量:{cloneableRepo.Count}");
Person copiedPerson = cloneableRepo.GetCopy(0);
copiedPerson.Name = "复制的张三";
copiedPerson.Email = "copied@email.com";
Console.WriteLine($"原始人员:{cloneableRepo.GetAllCopies()[0]}");
Console.WriteLine($"复制人员:{copiedPerson}");
Console.WriteLine($"是同一个对象:{ReferenceEquals(cloneableRepo.GetCopy(0), copiedPerson)}");
List<Person> allCopies = cloneableRepo.GetAllCopies();
Console.WriteLine($"所有副本数量:{allCopies.Count}");
Person newFromFactory = cloneableRepo.CreateNew();
Console.WriteLine($"工厂创建的新人员:{newFromFactory}");
}
}
4. 总结
本章深入介绍了C#泛型编程的核心概念:
- 泛型基础:泛型的概念、优势和基本使用
- 泛型类型:泛型类、泛型接口的定义和实现
- 泛型方法:泛型方法、泛型委托的使用
- 泛型约束:各种约束类型的使用和组合
关键要点: - 泛型提供类型安全和性能优势 - 避免装箱拆箱和类型转换 - 合理使用泛型约束限制类型参数 - 泛型方法可以独立于类进行类型推断 - 泛型委托支持函数式编程模式 - 多重约束可以组合使用
下一章预告: 下一章我们将学习委托和事件,包括委托的定义、多播委托、事件机制和观察者模式的实现。