值类型、引用类型的区别
值类型存放在栈上,引用类型存放在堆上,结构体是值类型,类是引用类型,string是引用类型
值类型
C#支持哪几种预定义的值类型?
值类型是一种由类型的实际值表示的数据类型。
主要包括五个类型:整型、浮点型、字符型、bool型、decimal型,每一个类型分别由多个内置类型组成。
内置类型详情见如下链接
内置类型.
不同值类型的内置类型需要注意其取值范围,记得其大致的范围。如uint,当取值超过4300000000时将会溢出,这在程序测试时经常出现,需要注意。
值类型的一些特点
值类型分配在线程堆栈上
值类型继承自valueType,valueType继承自System.Object
值类型变量可以直接分配给一个值。
值类型根据不同的类型有不同的默认值。如int为默认值为0。
引用类型
c#支持哪几种引用类型?
引用类型是指由类型的实际值引用表示的数据类型。
引用类型不包含存储在变量中的实际数据,但它们包含对变量的引用。
简单的说,它们指的是一个内存位置,类似于指针。
内置的 引用类型有:object、dynamic 和 string。
引用类型的一些特点
引用类型分配在托管堆上。
引用类型直接继承自System.Object。
引用类型的默认值为null。
我们由int[] arr = new int[]来理解是怎样为引用类型分配内存的。
主函数先进栈,在栈中定义一个变量arr。此时并未在堆上开辟内存,只在栈上有一小块儿内存用于储存一个地址。
接下来为arr赋值,但是右边不是一个具体值,是一个实体。这时便在堆中开辟了一块儿内存用于储存实体(分配的地址和初始化的值),
此时通过=将堆中的内存地址赋值给变量,因此引用类型储存的为变量的地址。
区别:
要弄清这个问题需要先了解值类型与引用类型的基本概览。
值类型实例通常分配在线程的堆栈上
引用类型实例分配在托管堆上,变量保存了实例数据的内存引用。
例如 object test = new object() ,那么new object() 则在托管堆上开辟的一块内存用于储存实例地址以及实例数据,而test则保存了new object() 的引用的指针,并且是保存在堆栈上的。
引用类型讲解详见: 引用类型.
弄清基本概念后我们从三个方面来分析其区别。
1,赋值的区别
值类型的赋值只是进行数据赋值。
引用类型的赋值是把对象的引用的指针赋值给变量的(就是我们经常说的,保存的是对象的引用)
2、继承结构的区别
值类型继承与system.valuetype,引用类型继承于system.object。
3,内存分配的区别
值类型分配在栈上,引用类型在堆上。
注意:
1,C#的垃圾回收机制会控制回收堆上开辟的内存,因此引用类型会由GC自动回收或由程序员手动回收,而值类型在作用域结束时会自行释放。由于减少了托管堆的压力,因此值类型拥有性能优势。
2,通常自己定义的类型都是引用类型。
3,最简单有效的方法是看它是否继承于system.valuetype。
区别:
-
值类型通常被分配在栈上,它的变量直接包含变量的实例,使用效率比较高。
-
引用类型分配在托管堆上,引用类型的变量通常包含一个指向实例的指针,变量通过该指针来引用实例。
-
值类型继承自 ValueType (注意:而 System. ValueType 又继承自 System.Object);而引用类型继承自 System.Object。
-
值类型变量包含其实例数据,每个变量保存了其本身的数据拷贝(副本),因此在默认情况下,值类型的参数传递不会影响参数本身;而引用类型变量保存了其数据的引用地址,因此以引用方式进行参数传递时会影响到参数本身,因为两个变量会引用了内存中的同一块地耻。
-
值类型有两种表示:装箱与拆箱;引用类型只有装箱一种形式。我会在下节以专门的篇幅来深入讨论这个话题。
-
典型的值类型为:struct,ewrim 以及六量的它置信类型;而能称为类的都可以说是引用类型。
-
值类型的内存不由 GC(垃圾回收,Gabage Collection)控制,作用域结束时,值类型会自行释放,減少了托管堆的压力,因此具有性能上的优势。例如,通常 struct 比 class 更高效;而引用类型的内存回收,由 GC 来完成,微软甚至建议用户最好不要自行释放内存。
-
值类型是密封的(sealed),因此值类型不能作为其他任何类型的基类,但是可以单继承或者多继承接口;而引用类型一般都有继承性。
-
值类型不具有多态性;而引用类型有多态性。
-
值类型变量不可为 null 值,值类型都会自行初始化为 0 值;而引用类型变量默认情况下,创建为 null 值,表示没有指向任何托管堆的引用地址。对值为 null的引用类型的任何操作,都会抛出 NullReferenceException 异常。
-
值类型有两种状态:装箱和未装箱,运行库提供了所有值类型的已装箱形式;而引用类型通常只有一种形式:装箱
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)