c# 装箱和拆箱是什么
技术百科
煙雲
发布时间:2026-01-21
浏览: 次 装箱和拆箱是值类型与引用类型转换时真实发生的堆分配与数据拷贝操作,非语法糖;装箱触发于值类型被当作引用类型使用(如赋值给object、调用object参数方法、实现接口等),拆箱需严格类型匹配,否则抛InvalidCastException。
装箱和拆箱是 C# 中值类型与引用类型之间隐式/显式转换的底层机制,不是语法糖,而是真实发生堆分配和数据拷贝的操作。它看起来只是类型转换,但每次装箱都会在托管堆上 new 一个对象,带来 GC 压力和性能损耗;拆箱虽不分配内存,但必须做类型检查 + 数据复制,类型不匹配就直接抛 InvalidCastException。

装箱不是你写了 object 才触发,而是只要值类型被“当作引用类型用”,CLR 就会介入:
-
int i = 42; object o = i;—— 最直白的装箱 -
Console.WriteLine(i);——WriteLine(object)重载被选中,i自动装箱 -
ArrayList list = new ArrayList(); list.Add(i);——Add(object)参数强制装箱 -
int i = 100; IComparable cmp = i;—— 值类型实现接口,赋值即装箱(哪怕IComparable也逃不掉) -
string.Format("{0}", i)或 $"{i}"插值中混入值类型 —— 格式化方法内部仍走object路径
拆箱为什么总报 InvalidCastException?
拆箱不是“取值”,而是“验证 + 复制”:运行时必须确认堆上的对象确实是你要拆的那个值类型,且不能绕过原始装箱路径。常见翻车点:
- 装箱的是
int,却试图拆成long:int i = 5; object o = i; long l = (long)o;→ 立刻炸 - 从非装箱来源强转:
object o = "hello"; int x = (int)o;→ 不是值类型装箱而来,必崩 - 泛型集合里存的是
int,但误用非泛型 API 取出:List—— 这里list = new List { 1 }; object o = list[0]; int x = (int)o; list[0]本身没装箱(泛型避免了),但一旦你把它塞进object再拿出来,就人为制造了一次装箱+拆箱
怎么真正避开装箱?别只记“用泛型”
泛型集合(List)和泛型方法(void Log)确实能绕过 object,但还有更隐蔽的坑:
- 接口装箱躲不开:即使你用
List,往里加int依然会装箱 —— 因为int是值类型,实现IComparable就意味着要包装成引用 - 委托参数也是雷区:
Action→42被装箱传入 - 高性能循环里,连
foreach (var x in array)都可能触发(如果array是非泛型Array类型) - 真正零开销替代:用
Span、ReadOnlySpan处理临时数据;对必须抽象的场景,优先定义泛型接口(IProcessor)而非非泛型接口(IProcessor)
static void AvoidBoxingDemo()
{
// ❌ 低效:每次循环都装箱
for (int i = 0; i < 1000; i++)
Console.WriteLine(i); // 调用 WriteLine(object)
// ✅ 高效:复用泛型重载
for (int i = 0; i < 1000; i++)
Console.WriteLine(i.ToString()); // ToString() 返回 string,无装箱
// ✅ 更优:用泛型方法封装
static void SafeWritezuojiankuohaophpcnTyoujiankuohaophpcn(T value) => Console.WriteLine(value);
for (int i = 0; i < 1000; i++)
SafeWrite(i); // T 推导为 int,调用 WriteLine(int)}
最容易被忽略的一点:装箱不是“错误”,它是 C# 统一类型系统的必要代价;但它的开销在高频路径(如日志、序列化、游戏帧循环)里会指数级放大。与其等 profiler 报警,不如在写 object 参数、用非泛型集合、或把 struct 赋给接口时,下意识停半秒,问自己一句:“这个值,真需要变成引用吗?”
# 的是
# 就会
# 会在
# 你要
# 把它
# 它是
# 写了
# 什么时候
# 而来
# 一句
# format
# 循环
# 对象
# 堆
# String
# int
# void
# 值类型
# 泛型
# c#
# 接口
# 委托
# console
# 为什么
# var
# foreach
# Struct
# char
# 类型转换
# 引用类型
# Object
# Array
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win11怎么关闭贴靠布局_Win11禁用窗口最大
- C#如何使用XPathNavigator高效查询X
- Python迭代器生成器进阶教程_节省内存与懒加载
- windows系统如何安装cab更新补丁_wind
- Mac的Time Machine怎么用_Mac系统
- Python列表推导式与字典推导式教程_简化代码高
- 如何使用Golang处理网络超时错误_Golang
- Python变量绑定机制_引用模型解析【教程】
- Windows10如何更改日期格式_Win10区域
- Windows 11怎么设置默认解压软件_Wind
- Win11声音忽大忽小怎么办 Win11音频增强功
- Python性能剖析高级教程_cProfileLi
- 如何在 Go 结构体中正确初始化 map 字段
- Django 测试数据库表缺失与字段未创建问题的完
- php嵌入式日志记录怎么实现_php将硬件数据写入
- Python面向对象实战讲解_类与设计模式深入理解
- 如何用正则与预处理结合精准拦截拼接式垃圾域名
- Win11怎么关闭通知消息_屏蔽Windows 1
- Windows10如何删除Windows.old_
- WindowsUSB驱动安装异常怎么办_USB驱动
- 如何优化Golang内存分配与GC调度_Golan
- Win11怎么开启专注模式_Windows11时钟
- C++如何获取CPU核心数?(std::threa
- Win11键盘快捷键大全_Windows 11常用
- 如何用正则表达式精确匹配最多含一个换行符的起止片段
- windows如何修改文件默认打开方式_windo
- Python网络超时处理_健壮性设计说明【指导】
- 如何使用Golang配置安全开发环境_防止敏感信息
- Win11关机快捷键是什么_Win11快速关机方法
- Bpmn 2.0的XML文件怎么画流程图
- 如何在Golang中使用replace替换模块_指
- Python网络日志追踪_请求定位解析【教程】
- Win10怎么限制单程序CPU占用上限_Win10
- Win11怎么恢复误删照片_Win11数据恢复工具
- c++怎么使用std::filesystem遍历文
- Win11怎么查看电脑配置_Win11硬件配置详细
- c++怎么使用类型萃取type_traits_c+
- 如何诊断并终止卡死的 multiprocessin
- php中::能用于接口静态方法吗_接口静态方法调用
- Win10怎样安装Word样式库_Win10安装W
- Go语言中CookieJar的持久化机制解析:内存
- Windows电脑如何截屏?(四种快捷方法)
- Win11蓝牙开关不见了怎么办_Win11蓝牙驱动
- Windows11怎样开启游戏模式_Windows
- Win10如何卸载预装Edge扩展_Win10卸载
- Win11怎么关闭自动维护 Win11禁用系统自动
- Windows10如何更改盘符名称_Win10重命
- 用Python构建微服务架构实践_FastAPI与
- c++中如何使用std::variant_c++1
- 如何使用Golang实现容器自动化运维_Golan

QQ客服