在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
最近博客园上连续出现了几篇关于堆VS栈 值类型VS引用类型的文章。
一个是关于C# 堆VS栈的,深入浅出,动图清晰明了,链接如下 二是从Eric Lippert(Eric Lippert is a principal developer on the C# compiler team)的文章演变出的两篇,链接如下
下面是我的思考和总结,希望能与大家分享和讨论。 值类型和引用类型的区别最近和同事一起面试时也经常问这个问题,被面的同学很多回答为“值类型存储在栈里,引用类型存储在堆里”,首先我们先不去深究这个说法是否准确(上面的文章里已经说的很清楚)。 值类型和引用类型的区别是存储位置的不同吗? Eric Lippert给出的答案----值类型和引用类型的区别在语义层面,与存储位置无关。存储位置是C#编译运行时的分配,是实现细节。 或许C# compiler的未来版本中,值类型也可能不存储在栈里; 或者某一个系统平台中并不存在堆和栈的概念。 结论 “值类型和引用类型的区别,与存储位置无关”。
值类型和引用类型区别是什么呢?Eric Lippert说 - 值类型和引用类型的区别在语义层面。要怎么理解?我们思考的视角应该是C#语言语义和使用上。 结论 “值类型传递的是值(不同的实例,互不影响),引用类型传递的是引用(同一个实例,互相影响)” 如同一句废话!那我们试着换几种方式来描述(可能不准确) 1. 值类型是私有的,是持有者自己的东西;引用类型是共享的,大家共有的东西。 2. 值类型是多实例的,每次传递都创建新实例;引用类型是单实例的,每次传递都是同一个实例,如设计模式中的单例。 3. 值类型的生命周期和持有者相同;引用类型的生命周期和持有者不同。(有关生命周期的言论)
为什么在讨论值类型和引用类型时,总会出现堆和栈?如何实现值类型和引用类型的存储? 有两种存储方式可供选择 一 直接存储的优点是性能高,缺点是共享不方便。(栈或者堆上) 二 间接存储的优点是共享方便,缺点是多了一次跳转,有性能损失。(堆上)
我们要的关注哪些问题?性能,共享方式(生命周期) 值类型是不共享的,它的生命周期和持有者相同,所以可以直接存储,如果间接存储,会多一次跳转,没有意义的性能损失。 引用类型是共享的,它的生命周期和持有者不同,所以采用间接存储,如果直接存储,是很难实现共享和生命周期的不同。 结论 值类型是直接存储,引用类型是间接存储。是基于实现的考量,不是值类型和引用类型的区别。 生命周期是从实现角度思考的推论,也不是值类型和引用类型的区别。
为什么存在两种类型(值类型和引用类型),而不仅仅是一种类型(值类型或者引用类型)?思考后发现,所有值类型都可以被引用类型所替代,那为什么要有值类型呢?没有得出理想的答案,推测有两种可能 一 历史传承。 二 基于性能的考量。这个应该是实现级别的事情,为什么被暴露在语言级别上?没有办法解决吗?(对于值来说,引用类型多了一次跳转;对于引用来说,值的传递多了一次深克隆)
何时用值类型(struct),何时用引用类型(class)?在工作中很少(几乎没有)使用struct,因为性能上的收益远远无法弥补维护成本的损失。 (不能要求每个开发人员都很了解struct和class的不同,并在修改代码时意识到使用的是struct而不是class)
总结值和引用类型的区别是语言和使用级别的 值类型传递的是值(不同的实例,互不影响),引用类型传递的是引用(同一个实例,互相影响) 有关值类型和引用类型储存在栈或者堆上的言论,是基于实现细节的思考,是当前的实现方式,不是值类型和引用类型的区别。 有关值类型和引用类型生命周期的言论,是基于实现细节的思考,是当前的实现方式,不是值类型和引用类型的区别。 值类型(struct)更多是性能上的收益,C#中定义的基础值类型已经足够,开发中尽量避免定义值类型(struct)。
期待看到不同的观点和理由!
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论