VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > c#编程 >
  • 泛型约束——限制类型参数

泛型约束——限制类型参数

  1. 泛型约束的核心作用
    泛型的灵活性让代码适配任意类型,但无限制的泛型可能导致类型不安全(比如调用不存在的方法)或性能损耗(比如频繁装箱拆箱)。泛型约束通过where关键字限制类型参数的合法范围,确保:
    代码能安全调用类型参数的特定方法/属性;
    避免不必要的类型转换;
    提高编译时类型检查的严格性。
  2. 约束的语法与常用类型
    泛型约束的语法为:where 类型参数 : 约束条件。多个约束用逗号分隔,new()约束必须放在最后。
    2.1 常用约束类型
约束语法 作用说明 示例代码
where T : class T必须是引用类型(如string、自定义类、接口实例) public class Repository where T : class
where T : struct T必须是值类型(如int、double、DateTime,不包括Nullable) public class Calculator where T : struct
where T : new() T必须有无参默认构造函数(允许创建T的实例) public class Factory where T : new()
where T : BaseClass T必须继承自BaseClass(可调用BaseClass的方法/属性) public class AnimalShelter where T : Animal
where T : IInterface T必须实现IInterface(可调用接口的方法/属性) public class Sorter where T : IComparable
where T : U T必须是U的子类或同一类型(泛型类型之间的约束) public class Container<T, U> where T : U
  1. 实例:带约束的泛型数据存储类
    我们以泛型仓储类为例,展示约束的实际应用。该类要求类型参数T满足:
    是引用类型(class);
    有默认构造函数(new());
    实现IEntity接口(包含Id属性)。
    3.1 完整代码实现
    csharp
	using System;
	using System.Collections.Generic;
	
	// 1. 定义接口:规范实体类必须有Id属性
	public interface IEntity
	{
	int Id { get; set; }
	}
	
	// 2. 自定义实体类:实现IEntity接口
	public class User : IEntity
	{
	public int Id { get; set; }
	public string Name { get; set; }
	public int Age { get; set; }
	// 无参构造函数(满足new()约束)
	public User() {}
	}
	
	// 3. 泛型仓储类:带多重约束
	public class GenericRepository<T> where T : class, IEntity, new()
	{
	private List<T> _data = new List<T>();
	
	// 添加实体:依赖IEntity的Id属性
	public void Add(T entity)
	{
	if (entity.Id == 0) throw new ArgumentException("Id不能为空");
	_data.Add(entity);
	Console.WriteLine($"添加实体成功:Id={entity.Id}, Type={typeof(T).Name}");
	}
	
	// 根据Id查询实体:依赖IEntity的Id属性
	public T GetById(int id)
	{
	return _data.Find(e => e.Id == id);
	}
	
	// 创建新实体:依赖new()约束
	public T CreateNew()
	{
	return new T(); // 只有T有默认构造函数时才能调用
	}
	}
	
	// 4. 测试代码
	class Program
	{
	static void Main()
	{
	var repo = new GenericRepository<User>();
	
	// 创建新实体(依赖new()约束)
	var user = repo.CreateNew();
	user.Id = 1;
	user.Name = "张三";
	user.Age = 25;
	
	// 添加实体(依赖IEntity的Id属性)
	repo.Add(user);
	
	// 查询实体
	var foundUser = repo.GetById(1);
	Console.WriteLine($"查询结果:Name={foundUser.Name}, Age={foundUser.Age}");
	}
	}

3.2 逐行代码讲解
IEntity接口:定义Id属性,规范实体类的基本结构;
User类:实现IEntity接口,提供无参构造函数(满足new()约束);
GenericRepository的约束:
oclass:确保T是引用类型(避免值类型的装箱操作);
oIEntity:确保T有Id属性(允许调用entity.Id);
onew():允许通过new T()创建实例;
Add方法:检查Id是否为空(依赖IEntity),添加实体到列表;
CreateNew方法:直接创建T的实例(依赖new()约束);
测试逻辑:创建仓储→生成新用户→添加→查询,验证约束的有效性。
输出结果:

	添加实体成功:Id=1, Type=User 
	查询结果:Name=张三, Age=25
  1. 基础知识拓展
    4.1 约束的顺序规则
    当使用多重约束时,需遵循以下顺序:
    1.引用类型约束(class)或值类型约束(struct);
    2.基类约束(BaseClass);
    3.接口约束(IInterface);
    4.泛型类型约束(U);
    5.new()约束(必须放在最后)。
    错误示例:where T : new(), class(new()在前,编译报错);
    正确示例:where T : class, IEntity, new()。
    4.2 无约束的泛型
    若未指定约束,类型参数默认隐式约束为object,只能调用object的方法(如ToString()、Equals())。例如:
    csharp
	public class Unconstrained<T>
	{
	public void Print(T item)
	{
	Console.WriteLine(item.ToString()); // 只能调用object的方法
	}
	}

缺点:无法调用T的特定方法,需强制类型转换(风险高)。
4.3 约束的好处
类型安全:编译时检查类型参数是否符合要求,避免运行时错误;
性能优化:减少装箱拆箱操作(如struct约束避免值类型转object);
代码可读性:约束明确告诉开发者类型参数的预期用途;
功能扩展:允许调用约束类型的方法(如IComparable的CompareTo)。
5. 总结
泛型约束是泛型编程的“安全网”,通过限制类型参vb.net教程C#教程python教程SQL教程access 2010教程数的范围,让泛型代码既灵活又可靠。核心要点:
用where关键字定义约束;
常用约束包括class、struct、new()、基类/接口约束;
多重约束需遵循顺序规则;
约束能提升类型安全、性能和代码可读性。
6. 练习
实现一个泛型排序类GenericSorter,要求:
1.T必须实现IComparable接口(支持比较);
2.提供Sort(List list)方法,对列表进行升序排序;
3.测试代码用int、string和自定义类(如Product,实现IComparable)验证。
提示:排序可使用冒泡排序或Array.Sort方法(依赖IComparable)。
(本节完)
下一章:泛型进阶——协变与逆变(深入泛型的类型转换特性)。

本站原创,转载请注明出处:


相关教程