关于接口是值类型还是引用类型的猜测
虽然工作也有几年时间了,但时常能暴露出基础知识薄弱的问题,因此,有空闲时间时总喜欢把缺下的功课补齐。
今天想讨论的是,接口到底是引用类型还是值类型。
要想说清楚接口到底是引用类型还是值类型,就需要先解释一下值类型跟引用类型。
值类型,简单理解就是继承自ValueType的类型,除过可空类型(如int?,bool?)外,值不能为null,通常情况下存储在栈中。而引用类型不从ValueType继承,其值可以为null,存储在托管堆中,由GC负责清理。
既然大致了解了什么是值类型和引用类型,或者说,值类型和引用类型的区别,那么有一个简单粗暴的办法判定接口类型问题----可以调用Object的实例方法GetType(),得到Type实例。通过Type的实例属性BaseType,直接判断接口的基类型。只是,接口可以理解成一种抽象类型,抽象类型是不允许实例化的,只能由实现类实例化。值类型以及引用类型都可以实现接口,所以通过基类型的方法并非个好方法。
偶然间发现一段代码:
const int i = 5;
IFormattable ftt = i;
这里不得不提到另一对概念,装箱和拆箱。装箱会将值类型经过一系列包装放到一个箱子,转换为引用类型,然后存放到托管堆上面。拆箱和这个过程相反,从托管堆上面拿到这个箱子,经过一些列的拆分操作,从引用类型转换成值类型。当然,拆箱过程涉及类型检查,这里不细说。总之,装箱可以简单理解为值类型-->引用类型,拆箱可以简单理解为引用类型-->值类型。有了这些理解就够了。
再来观察上面的代码段,i 为int类型,int类型是系统自定义的值类型。IFormattable是接口类型,如果接口类型是值类型,那么IFormattable ftt = i 是值类型到值类型的转换,将不存在装箱操作。如果接口类型是引用类型,那么IFormattable ftt = i 必然存在从值类型到引用类型的转换,即装箱操作。那就不多说了,采用IL查看工具看下源码就明白了!

using System; namespace Interview { class TestInterfaceType { public void Test() { const int i = 5; IFormattable ftt = i; } } }
上面是源码,下面是IL源码(可以通过ILSpy、Reflactor或者VS 自带的ILDasm工具查看IL代码):

.method public hidebysig instance void Test () cil managed { // Method begins at RVA 0x2330 // Code size 9 (0x9) .maxstack 1 .locals init ( [0] class [mscorlib]System.IFormattable ftt ) IL_0000: nop IL_0001: ldc.i4.5 IL_0002: box [mscorlib]System.Int32 IL_0007: stloc.0 IL_0008: ret } // end of method TestInterfaceType::Test
亮点在于 IL_0002: box [mscorlib]System.Int32 这一行,其中 box 就代表装箱指令。基本就可以断定,接口属于引用类型了。
当然,这些只是个人的一些理解,如果有不妥的地方,欢迎各位指正。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?