C#泛型类用class ClassName语法声明,T是类型占位符,必须在实例化时指定具体类型(如Box),不可省略;需用where约束限定T的能力(如class、new()、接口等),否则无法调用相应成员;静态字段按封闭类型隔离,继承时需保持类型参数一致。

直接说结论:C# 定义泛型类用 class ClassName 语法,核心是把类型占位符(如 T)放在类名后尖括号里,所有内部用到该类型的字段、参数、返回值都用这个占位符代替——不是“加个泛型关键字”就完事,类型约束和实例化时机才是实际开发中最容易出错的地方。
泛型类的基本写法和常见错误
最简形式就是声明一个带类型参数的类,比如实现一个可存任意类型值的容器:
public class Box<t>
{
public T Value { get; set; }
}</t>
但新手常踩的坑是:直接 new Box 不行,必须指定具体类型,比如 new Box 或 new Box。编译器不会帮你猜 T 是什么;如果写了 Box b = new Box();,会报错 The type arguments for method '...' cannot be inferred。
-
T在类体内是“类型占位符”,不是变量名,不能用typeof(T)做运行时判断(除非加where T : class约束并配合default或反射) - 字段、属性、方法参数、返回值中只要涉及该类型,都必须统一用
T,不能混用object或硬编码具体类型 - 泛型类在 IL 层面会为每个实际类型生成独立的封闭类型(
Box和Box是两个完全不同的类型),所以它们之间不能隐式转换
什么时候必须加 where 约束?
当你需要在泛型类内部对 T 做操作时,编译器需要知道它能干什么。比如想调用 .ToString()、做判空、或用 new T(),就必须加约束:
public class Repository<t> where T : class, new()
{
public T CreateNew() => new T(); // ✅ 允许
public void Print(T item) => Console.WriteLine(item?.ToString()); // ✅ 允许判空
}</t>
没加 where T : class 就用 item?.ToString(),会报错 Operator '?' cannot be applied to operand of type 'T';没加 new() 就写 new T(),会报 Cannot create an instance of the variable type 'T' because it does not have the new() constraint。
-
where T : struct→ 限定值类型,可用于比较、装箱控制 -
where T : IComparable→ 要求实现接口,才能调用CompareTo - 多个约束用逗号分隔,
class或struct必须放最前
泛型类和继承/实现接口的实际搭配
泛型类可以继承非泛型基类,也可以继承其他泛型类,但父类的类型参数必须被明确传递。接口也一样,实现 IEnumerable 就得把 T 传下去:
public class Queue<t> : IEnumerable<t private readonly list> _items = new(); <pre class="brush:php;toolbar:false;">public IEnumerator<t> GetEnumerator() => _items.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();</t>
}
这里 IEnumerator 的 T 必须和类声明的 T 一致,否则编译失败。如果写成 IEnumerable,那这个类就只能存字符串,失去泛型意义。
- 泛型基类被继承时,子类要么继续泛型(
class MyQueue),要么固定类型(: Queue class StringQueue : Queue) - 不能在子类里“重定义”父类的
T,比如父类是Base,子类写Derived : Base是合法的,但Derived : Base就不再是泛型类了 - 静态字段在泛型类中是按封闭类型隔离的:
Box和.Count Box是两个独立变量.Count
泛型类真正难的不是写法,而是设计时想清楚:这个 T 到底要承担什么职责?它会不会被误用成 object 的替代品?约束加太松会导致运行时异常,加太紧又丧失灵活性。多数项目里,一个泛型类只处理一种核心抽象(比如数据容器、策略执行器、序列化适配器),而不是试图“通用一切”。











