c# 泛型 T 是什么意思

来源:这里教程网 时间:2026-02-21 17:36:17 作者:

T 就是你用的时候才填进去的类型占位符,不是某种固定类型,也不是关键字,它就是个“代号”。 比如

List<t></t>
本身不能直接 new,你必须写成
List<int></int>
List<string></string>
—— 这时
T
才被替换成具体类型,编译器才真正生成对应代码。

为什么非得用 T,不用 object 或 dynamic?

object
看似通用,但会引发两个硬伤:

值类型(如
int
)存进
List<object></object>
装箱,取出来再拆箱,性能损耗明显,尤其高频操作时
类型不安全:你往里加了个
string
,编译器不管;但后面按
int
强转,运行时直接抛
InvalidCastException
dynamic
更糟:完全绕过编译检查,连 IDE 提示、重构支持都丢了

List<t></t>
在编译期就锁死类型——
list.Add("abc")
List<int></int>
里加,根本过不了编译

T 可以换成别的名字吗?

完全可以。

T
只是约定俗成的单字母缩写,源于 “Type”。你写
class Box<titem></titem>
class Repository<tentity></tentity>
甚至
class Pipe<theactualthing></theactualthing>
都合法。

但要注意:

多个泛型参数时,务必用有意义的名,比如
Dictionary<tkey tvalue></tkey>
,没人会写
Dictionary<t u></t>
接口或委托中常见命名习惯:
IComparer<t></t>
Predicate<t></t>
Func<tinput toutput></tinput>
自定义泛型类如果只用一个参数,坚持用
T
最省事,团队也一眼能懂

泛型方法里的 T 怎么用?

泛型方法把类型选择权交给调用方,而不是类本身。例如:

public static T GetFirst<T>(IList<T> list)
{
    return list.Count > 0 ? list[0] : default;
}

调用时可以显式指定:

GetFirst<string>(myStrings)</string>
,也可以让编译器推断:
GetFirst(myInts)
(前提是
myInts
List<int></int>
这类明确类型的集合)。

容易踩的坑:

别在泛型方法里对
T
==
!=
判断(值类型/引用类型行为不一致),改用
EqualityComparer<t>.Default.Equals(a, b)</t>
如果需要约束
T
必须有无参构造函数,得加
where T : new()
别试图在方法内写
typeof(T) == typeof(int)
来做运行时分支——这违背泛型本意,也影响 JIT 优化

真正关键的一点是:T 不是运行时“动态决定”的类型,而是编译时由你填写后,CLR 为每种实际类型(

int
Customer
Guid
)生成独立的专用版本。所以它既类型安全,又没装箱开销——这不是妥协出来的方案,是 C# 泛型设计的底层逻辑。

相关推荐

热文推荐