C#泛型约束完整示例(含全部约束类型 + 注释)
C# 7.3 保留了所有主流泛型约束,仅小幅优化语法兼容,下面分基础约束、组合约束、特殊约束逐一实现,代码可直接运行,附带详细说明。
一、先回顾泛型约束分类
- 基类约束:
类名要求泛型参数必须继承自该类 - 接口约束:
接口名要求实现指定接口 - 引用类型约束:
class必须是引用类型(类、接口、数组、委托) - 值类型约束:
struct必须是值类型(结构体、枚举,不可为可空类型) - 无参数构造函数约束:
new()必须拥有公共无参构造 - 组合约束:多个约束叠加,用
,分隔 - 类型参数约束(裸类型约束):
T : U泛型参数继承另一个泛型参数
二、完整可运行代码(C# 7.3)
using System;
/*
* 定义:泛型约束指的就是声明泛型的时候指定一些约束条件,那么在使用的时候会自行进行约束条件的判断。
*
* 举例:public struct Nullable<T> where T : struct
*
* 常见的泛型约束:
*
* 1、<T> where T : struct 指定类型必须是值类型
* 2、<T> where T : class 指定类型必须是引用类型
* 3、<T> where T : new() 指定类型必须有无参数的构造函数,如果有其他约束,则new()约束必须放到最后
* 4、<T> where T : 类名约束 指定类型必须是某类或派生自某类,如果与其他接口共用,则放到接口前面;T要么是某类,要么是某类的子类或孙子类
* 5、<T> where T : 接口约束 指定类型必须是实现一个或多个接口
* 6、<T> where T : 多泛型约束 指定类型必须是约束泛型或约束泛型的子类;也叫多类型占位符约束
*/
namespace GenericConstraintDemo
{
#region 1. 准备测试基类、接口、结构体
// 基类
public class Animal
{
public virtual void Speak()
{
Console.WriteLine("动物发出声音");
}
}
// 接口
public interface IRunning
{
void Run();
}
// 继承基类+实现接口(用于约束测试)
public class Dog : Animal, IRunning
{
public override void Speak()
{
Console.WriteLine("汪汪汪");
}
public void Run()
{
Console.WriteLine("小狗快速奔跑");
}
}
// 结构体(值类型)
public struct Point
{
public int X;
public int Y;
}
// 带无参构造的普通类
public class Person
{
public Person() { } // 无参构造
public void SayHello()
{
Console.WriteLine("你好");
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("===== 1. 基类约束测试 =====");
TestBaseClassConstraint<Dog>();
Console.WriteLine("\n===== 2. 接口约束测试 =====");
TestInterfaceConstraint<Dog>();
Console.WriteLine("\n===== 3. 引用类型约束(class)测试 =====");
TestRefTypeConstraint<Dog>();
Console.WriteLine("\n===== 4. 值类型约束(struct)测试 =====");
TestValueTypeConstraint<Point>();
Console.WriteLine("\n===== 5. 无参构造函数约束(new())测试 =====");
TestNewConstraint<Person>();
Console.WriteLine("\n===== 6. 多约束组合测试 =====");
TestMultiConstraint<Dog>();
Console.WriteLine("\n===== 7. 裸类型参数约束测试 =====");
TestNakedTypeConstraint<Animal, Dog>();
}
#region 1. 基类约束:T 必须继承自 Animal
/// <summary>
/// 约束:T 是 Animal 或其子类
/// </summary>
/// <typeparam name="T"></typeparam>
public static void TestBaseClassConstraint<T>() where T : Animal
{
T animal = Activator.CreateInstance<T>();
animal.Speak();
}
#endregion
#region 2. 接口约束:T 必须实现 IRunning 接口
public static void TestInterfaceConstraint<T>() where T : IRunning
{
T obj = Activator.CreateInstance<T>();
obj.Run();
}
#endregion
#region 3. 引用类型约束:T 必须是 类/接口/数组 等引用类型
public static void TestRefTypeConstraint<T>() where T : class
{
Console.WriteLine($"当前泛型类型 {typeof(T)} 是引用类型");
}
#endregion
#region 4. 值类型约束:T 必须是 结构体/枚举(值类型)
public static void TestValueTypeConstraint<T>() where T : struct
{
Console.WriteLine($"当前泛型类型 {typeof(T)} 是值类型");
}
#endregion
#region 5. 无参构造函数约束:T 必须有公共无参构造
/// <summary>
/// 注意:new() 约束**必须放在所有约束最后**
/// </summary>
public static void TestNewConstraint<T>() where T : new()
{
T person = new T();
if (person is Person p)
{
p.SayHello();
}
}
#endregion
#region 6. 多约束组合(C#7.3 完全支持)
/// <summary>
/// 组合规则:基类/接口 → class/struct → new()
/// 约束顺序不能乱
/// </summary>
public static void TestMultiConstraint<T>() where T : Animal, IRunning, new()
{
T obj = new T();
obj.Speak();
obj.Run();
}
#endregion
#region 7. 裸类型参数约束(T 必须继承自 U)
/// <summary>
/// 语法:T : U 要求 T 是 U 的子类/实现类
/// </summary>
public static void TestNakedTypeConstraint<U, T>() where T : U
{
Console.WriteLine($"T({typeof(T)}) 继承自 U({typeof(U)})");
}
#endregion
}
}
三、运行输出结果
===== 1. 基类约束测试 =====
汪汪汪
===== 2. 接口约束测试 =====
小狗快速奔跑
===== 3. 引用类型约束(class)测试 =====
当前泛型类型 GenericConstraintDemo.Dog 是引用类型
===== 4. 值类型约束(struct)测试 =====
当前泛型类型 GenericConstraintDemo.Point 是值类型
===== 5. 无参构造函数约束(new())测试 =====
你好
===== 6. 多约束组合测试 =====
汪汪汪
小狗快速奔跑
===== 7. 裸类型参数约束测试 =====
T(GenericConstraintDemo.Dog) 继承自 U(GenericConstraintDemo.Animal)
四、C# 7.3 泛型约束核心规则(重点必记)
1. 约束书写固定顺序(报错高频点)
where T : [基类/接口], [class/struct], [new()]
- 第一部分:基类(只能1个)+ 接口(多个)
- 第二部分:
class/struct(二选一,不能同时写) - 第三部分:
new()无参构造(永远放最后)
2. 关键限制说明
struct约束:不包含可空类型(如int?无法通过)new():要求公共无参构造,私有构造/有参构造都会编译报错- 基类约束只能写一个,接口可以写多个,用逗号分隔
- C# 7.3 对比旧版本:无语法删减,仅优化了泛型委托、元组、默认值等配套语法,约束逻辑完全一致
3. 编译报错示例(避坑)
- 顺序错误:
where T : new(), Animal→ 编译报错 - 同时写 class + struct:
where T : class, struct→ 编译报错 - 传入不符合约束的类型:
TestValueTypeConstraint<Dog>(); // Dog是类,不是struct → 报错
五、拓展:泛型方法 + 泛型类 双重示例
日常开发更多用泛型类,补充示例:
// 泛型类 + 组合约束
public class Repository<T> where T : Animal, new()
{
public T CreateInstance()
{
return new T();
}
public void ShowInfo()
{
var t = CreateInstance();
t.Speak();
}
}
// 调用
var repo = new Repository<Dog>();
repo.ShowInfo();

浙公网安备 33010602011771号