C# 泛型方法(原理、类型推断、多泛型参数)+泛型效率(普通类型 VS Object装箱 VS 泛型)

一、泛型核心概念(原文背诵)

泛型:广泛的不确定类型

定义方法时,不想固定参数类型、返回值类型,可以定义为泛型类型 T

核心思想:延迟指定类型

定义方法时不锁定类型,调用方法时传入具体类型,一套代码适配所有数据类型。


二、普通方法重载(泛型优化前)

代码

复制代码
//int专用方法
static int Test(int a)
{
    return 10;
}
//string专用方法
static string Test(string a)
{
    return "ss";
}

问题痛点

如果需要支持 int、string、bool、double 等多种类型,需要写无数个重载方法,代码冗余、重复度极高。

泛型就是为了解决:不同类型、相同逻辑,不用重复写代码


三、单泛型方法(核心基础)

泛型方法定义

复制代码
//<T> 声明泛型占位符
static T Test<T>(T a)
{
    return a;
}

语法规则(必背)

  1. <T>:声明泛型,T 是类型占位符,可以换任意字母(A、B、T1、T2)

  2. 方法中所有T 代表同一个类型

  3. 参数是 T、返回值也是 T,做到:传入什么类型,返回什么类型

调用方式

复制代码
// 1.显式指定类型
Console.WriteLine(Test<int>(10));
Console.WriteLine(Test<string>("aa"));
Console.WriteLine(Test<bool>(true));

// 2.泛型类型推断(简化写法)
Console.WriteLine(Test(new string[] { "aa" })); 

两种调用方式解析

显式调用 :手动写 <类型>,清晰直观

隐式推断 :编译器根据实参自动识别类型,可以省略 <>

上面代码推断结果:string[] 类型


四、同类型双参数泛型方法 Test1<T>

代码定义

复制代码
//两个参数必须是相同类型
static T Test1<T>(T a, T b)
{
    return b;
}

规则

只有一个泛型占位符 T,所以 a、b 必须是一模一样的类型

调用代码

复制代码
Test1<int>(10, 20); //显式指定int
Test1(10, 20);       //编译器自动推断int

五、双泛型参数方法 Test2<T1,T2>

代码定义

复制代码
//两个不同泛型,无返回值
static void Test2<T1,T2>(T1 a,T2 b)
{

}

核心规则

T1、T2 是两个独立类型,可以相同、可以不同

调用解析

复制代码
Test2<int, string>(10, "aa"); //T1=int  T2=string
Test2(10, new string[] { "aa" });//T1=int  T2=string[]
Test2(10,10);//T1=int  T2=int(两个泛型可以相同)

六、返回值+数组泛型方法 Test3<T1,T2>

代码定义

复制代码
//T1为返回值类型、第一个参数类型
//T2[] 代表泛型数组
static T1 Test3<T1,T2>(T1 a, T2[] b)
{
    return a;
}

参数解析

  1. 第一个参数:普通泛型 T1

  2. 第二个参数:泛型数组 T2\[\]

  3. 返回值固定为 T1 类型

调用解析

复制代码
Test3<int, int>(10, new int[] { 1, 2, 3 }); 
//T1=int  T2=int  int数组

Test3(10, new string[] { "aa" });
//编译器自动推断 T1=int  T2=string string数组

七、泛型两大调用方式(必考)

1. 显式调用

手动指定类型:方法名<类型>(参数)

适合:类型模糊、编译器无法推断的场景

2. 隐式类型推断(简化)

直接写参数,省略 <>

编译器根据实参自动匹配泛型类型

开发中最常用


八、单泛型 VS 多泛型 核心区别

1. 单个泛型 <T>

所有 T 类型必须统一

适合:参数、返回值类型一致的场景

2. 多个泛型 <T1,T2>

T1、T2 相互独立

可以一同一不同,适配多个不同类型参数场景


九、泛型满分简答题(直接背)

1. 什么是泛型?

泛型是一种延迟确定数据类型的技术,定义方法时不固定参数和返回值类型,通过 <T> 声明占位类型,在调用方法时根据传入参数确定具体类型,实现一套代码适配多种数据类型,解决代码冗余问题。

2. 泛型的优点?

避免方法重载冗余、代码复用性高、保证类型安全、无需装箱拆箱、程序效率更高。

3. 多个泛型参数的特点?

多个泛型占位符相互独立,类型可以相同也可以不同,灵活适配多类型参数场景。


十、终极背诵口诀

泛型T是占位符,定义不把类型束

调用传参定类型,延迟绑定真舒服

单T类型必须同,多T独立互不冲

可推断可显式,一套代码通万物

---------泛型效率(普通类型 VS Object装箱 VS 泛型)------------

一、代码功能概述

本案例通过 Stopwatch 计时器,循环执行海量次数,对比三种方法的执行效率:

  • Test1:固定值类型参数 int

  • Test2:父类对象参数 object(存在装箱拆箱)

  • Test3:泛型参数T

通过实际运行耗时,验证泛型无装箱拆箱、效率接近原生值类型的核心特性。


二、完整运行结果(实测标准数据)

循环次数:1亿次

  • 普通值类型方法 Test1:3ms

  • 泛型方法 Test3:4ms

  • object装箱方法 Test2:10ms(最慢)

效率排行:固定值类型 > 泛型 > object装箱


三、三种方法逐一带底层原理解析

1. 普通值类型方法 Test1(int a)

复制代码
static void Test1(int a)
{

}
底层原理

参数直接接收 栈内存值类型,无需类型转换、无需装箱、无需拆箱。

编译时类型已经确定,运行时直接执行,效率最高

优缺点

✅ 效率极高,无性能损耗

❌ 只能适配单一类型,复用性极差,每种类型都要重载方法


2. Object 参数方法 Test2(object a)

复制代码
static void Test2(object a)
{

}
底层原理(重难点)

C# 中 object 是所有类型的父类

int 10 传给 object 参数时,发生:装箱(装箱转换)

装箱过程

  1. 在堆中开辟新内存

  2. 将栈中 int 值拷贝到堆内存

  3. 栈上存储堆地址引用

海量循环下,频繁装箱会产生大量 GC垃圾内存,极大拖慢效率。

优缺点

✅ 可以接收任意类型,复用性高

存在装箱拆箱,性能极差


3. 泛型方法 Test3<T>(T a)

复制代码
static void Test3<T>(T a)
{

}
底层原理(核心考点)

泛型的本质:编译时预留类型占位,运行时根据传入类型生成专属方法

当传入 int 类型时,CLR 会自动生成一个 Test3(int a) 专属方法。

全程无装箱、无拆箱,直接操作值类型。

优缺点

完全没有装箱拆箱损耗,效率无限接近原生值类型

✅ 一套代码适配所有类型,复用性极强

❌ 相比原生固定类型,有极其微弱的初始化损耗(几乎可忽略)


四、核心结论(必背简答题)

1. 为什么泛型比 object 效率高?

object 参数接收值类型会发生装箱拆箱 ,产生堆内存开销和 GC 压力;泛型在运行时会根据具体类型生成专属方法,全程无装箱拆箱,性能大幅提升。

2. 泛型和普通固定类型对比?

普通固定类型效率最高,但无法复用;泛型效率几乎持平原生类型,同时解决了代码复用问题,兼顾性能与复用性

3. 泛型最大优势总结

1. 类型安全(编译时报错,不会类型转换异常)

2. 避免装箱拆箱,性能极高

3. 一套代码适配多类型,彻底解决重载冗余


五、三者终极对比表(秒杀考点)

方法类型 是否装箱拆箱 执行效率 代码复用性 适用场景
固定值类型 最高 单一固定类型逻辑
Object 参数 有(严重损耗) 最低 老旧框架、弱类型场景(不推荐)
泛型方法 极高 最高 通用工具方法、集合类、公共逻辑

六、终极背诵口诀

固定类型最快行,不能复用代码长

Object装箱速度慢,频繁GC性能伤

泛型无箱性能强,复用安全两头香

相关推荐
L_09071 小时前
【C++】异常
开发语言·c++
世辰辰辰2 小时前
批量修改图片/文本名子
开发语言·python·批量修改文件名
rockey6273 小时前
基于AScript的SQL脚本语言发布啦!
sql·c#·.net·script·expression·动态脚本
z落落4 小时前
C# 四种特殊类:抽象类、密封类、静态类、部分类
开发语言·c#
VidDown4 小时前
Webhook 调试器:让第三方回调“原形毕露”
java·开发语言·javascript·编辑器·postman
装不满的克莱因瓶5 小时前
基于 OpenResty 扩展开发实现动态服务注册与发现能力
java·开发语言·架构·openresty
weixin_523185325 小时前
Java基础知识总结(四):引用数据类型与参数传递机制
java·开发语言·python
Nayxxu5 小时前
Claude API 生产稳定性设计:超时、降级、备用模型和告警怎么做
开发语言·php
王cb6 小时前
WinRT Server and Client c#
开发语言·c#