0

0

c# 装箱和拆箱是什么

煙雲

煙雲

发布时间:2026-01-21 10:37:44

|

888人浏览过

|

来源于php中文网

原创

装箱和拆箱是值类型与引用类型转换时真实发生的堆分配与数据拷贝操作,非语法糖;装箱触发于值类型被当作引用类型使用(如赋值给object、调用object参数方法、实现接口等),拆箱需严格类型匹配,否则抛InvalidCastException。

c# 装箱和拆箱是什么

装箱和拆箱是 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,却试图拆成 longint 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(T value))确实能绕过 object,但还有更隐蔽的坑:

Jobright
Jobright

专为北美求职者设计的AI求职助手平台

下载
  • 接口装箱躲不开:即使你用 List,往里加 int 依然会装箱 —— 因为 int 是值类型,实现 IComparable 就意味着要包装成引用
  • 委托参数也是雷区:Action act = Console.WriteLine; act(42);42 被装箱传入
  • 高性能循环里,连 foreach (var x in array) 都可能触发(如果 array 是非泛型 Array 类型)
  • 真正零开销替代:用 SpanReadOnlySpan 处理临时数据;对必须抽象的场景,优先定义泛型接口(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 赋给接口时,下意识停半秒,问自己一句:“这个值,真需要变成引用吗?”

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

338

2023.08.02

php中foreach用法
php中foreach用法

本专题整合了php中foreach用法的相关介绍,阅读专题下面的文章了解更多详细教程。

44

2025.12.04

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

639

2023.07.31

python中的format是什么意思
python中的format是什么意思

python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

431

2024.06.27

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

338

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

540

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

53

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

197

2025.08.29

Python GraphQL API 开发实战
Python GraphQL API 开发实战

本专题系统讲解 Python 在 GraphQL API 开发中的实际应用,涵盖 GraphQL 基础概念、Schema 设计、Query 与 Mutation 实现、权限控制、分页与性能优化,以及与现有 REST 服务和数据库的整合方式。通过完整示例,帮助学习者掌握 使用 Python 构建高扩展性、前后端协作友好的 GraphQL 接口服务,适用于中大型应用与复杂数据查询场景。

1

2026.01.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 7.2万人学习

C 教程
C 教程

共75课时 | 4.1万人学习

C++教程
C++教程

共115课时 | 13万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号