最近博客园上连续出现了几篇关于堆VS栈 值类型VS引用类型的文章。

一个是关于C# 堆VS栈的,深入浅出,动图清晰明了,链接如下

C#堆栈对比(Part One)

C#堆栈对比(Part Two)

C#堆栈对比(Part Three)

C#堆栈对比(Part Four)

二是从Eric Lippert(Eric Lippert is a principal developer on the C# compiler team)的文章演变出的两篇,链接如下

The Truth About Value Types

你真的了解C#中的值和引用吗?(上)

匹夫细说C#:不是“栈类型”的值类型,从生命周期聊存储位置

下面是我的思考和总结,希望能与大家分享和讨论。

值类型和引用类型的区别

最近和同事一起面试时也经常问这个问题,被面的同学很多回答为“值类型存储在栈里,引用类型存储在堆里”,首先我们先不去深究这个说法是否准确(上面的文章里已经说的很清楚)。

值类型和引用类型的区别是存储位置的不同吗

Eric Lippert给出的答案----值类型和引用类型的区别在语义层面,与存储位置无关。存储位置是C#编译运行时的分配,是实现细节。

  或许C# compiler的未来版本中,值类型也可能不存储在栈里;

  或者某一个系统平台中并不存在堆和栈的概念。

结论

  “值类型和引用类型的区别,与存储位置无关”。

值类型和引用类型区别是什么呢?

Eric Lippert说 - 值类型和引用类型的区别在语义层面。要怎么理解?我们思考的视角应该是C#语言语义和使用上。

结论

  “值类型传递的是值(不同的实例,互不影响),引用类型传递的是引用(同一个实例,互相影响)

    如同一句废话!那我们试着换几种方式来描述(可能不准确

    1. 值类型是私有的,是持有者自己的东西;引用类型是共享的,大家共有的东西。

    2. 值类型是多实例的,每次传递都创建新实例;引用类型是单实例的,每次传递都是同一个实例,如设计模式中的单例。

    3. 值类型的生命周期和持有者相同;引用类型的生命周期和持有者不同。(有关生命周期的言论)

为什么在讨论值类型和引用类型时,总会出现堆和栈?

如何实现值类型和引用类型的存储?

  有两种存储方式可供选择

    一 直接存储的优点是性能高,缺点是共享不方便。(栈或者堆上

    二 间接存储的优点是共享方便,缺点是多了一次跳转,有性能损失。(堆上

我们要的关注哪些问题?性能,共享方式(生命周期)

  值类型是不共享的,它的生命周期和持有者相同,所以可以直接存储,如果间接存储,会多一次跳转,没有意义的性能损失。

  引用类型是共享的,它的生命周期和持有者不同,所以采用间接存储,如果直接存储,是很难实现共享和生命周期的不同。

结论

  值类型是直接存储,引用类型是间接存储。是基于实现的考量,不是值类型和引用类型的区别。

  生命周期是从实现角度思考的推论,也不是值类型和引用类型的区别。

为什么存在两种类型(值类型和引用类型),而不仅仅是一种类型(值类型或者引用类型)?

思考后发现,所有值类型都可以被引用类型所替代,那为什么要有值类型呢?没有得出理想的答案,推测有两种可能

  一 历史传承。

  二 基于性能的考量。这个应该是实现级别的事情,为什么被暴露在语言级别上?没有办法解决吗?(对于值来说,引用类型多了一次跳转;对于引用来说,值的传递多了一次深克隆)

何时用值类型(struct),何时用引用类型(class)?

在工作中很少(几乎没有)使用struct,因为性能上的收益远远无法弥补维护成本的损失

(不能要求每个开发人员都很了解struct和class的不同,并在修改代码时意识到使用的是struct而不是class)

总结

值和引用类型的区别是语言和使用级别的

值类型传递的是值(不同的实例,互不影响),引用类型传递的是引用(同一个实例,互相影响)

有关值类型和引用类型储存在栈或者堆上的言论,是基于实现细节的思考,是当前的实现方式,不是值类型和引用类型的区别。

有关值类型和引用类型生命周期的言论,是基于实现细节的思考,是当前的实现方式,不是值类型和引用类型的区别。

值类型(struct)更多是性能上的收益,C#中定义的基础值类型已经足够,开发中尽量避免定义值类型(struct)

期待看到不同的观点和理由!

C# 堆VS栈 值类型VS引用类型的更多相关文章

  1. C# 托管与非托管类型 堆和栈 值类型与引用类型 装箱与拆箱

    一.托管类型与非托管类型 1.托管类型 托管类型包括 引用类型 以及 包含有引用类型或托管类型成员的结构. 引用类型 含引用类型或托管类型成员(字段.自动实现 get 访问器的属性)的结构 // 托管 ...

  2. C#【堆与栈 值类型 引用类型】

    先说C#中值类型和引用类型 概念: 1.值类型:数据存储在内存的堆栈中,从堆栈中可以快速地访问这些数据,因此,值类型表示实际的数据. 2.引用类型:表示指向存储在内存堆中的数据的指针或引用(包括类.接 ...

  3. 【译】.NET中六个重要的概念:栈、堆、值类型、引用类型、装箱和拆箱

    为何要翻译 一来是为了感受国外优秀技术社区知名博主的高质量文章,二来是为了复习对.NET技术的基础拾遗达到温故知新的效果,最后也是为了锻炼一下自己的英文读写能力.因为是首次翻译英文文章(哎,原谅我这个 ...

  4. .NET中的六个重要概念:栈、堆、值类型、引用类型、装箱和拆箱

    为何要翻译 一来是为了感受国外优秀技术社区知名博主的高质量文章,二来是为了复习对.NET技术的基础拾遗达到温故知新的效果,最后也是为了锻炼一下自己的英文读写能力.因为是首次翻译英文文章(哎,原谅我这个 ...

  5. [转] .NET中六个重要的概念:栈、堆、值类型、引用类型、装箱和拆箱

    为何要转载 一来是最近面试了几家公司,发现问的还都是这些的基础知识,二来是为了复习对.NET技术的基础拾遗达到温故知新的效果. 为什么有人说,不动笔不读书.我现在也是深有体会了,看过的东西不一定会记得 ...

  6. C#基础知识系列二(值类型和引用类型、可空类型、堆和栈、装箱和拆箱)

    前言 之前对几个没什么理解,只是简单的用过可空类型,也是知道怎么用,至于为什么,还真不太清楚,通过整理本文章学到了很多知识,也许对于以后的各种代码优化都有好处. 本文的重点就是:值类型直接存储其值,引 ...

  7. C# 值类型和引用类型

    一.基本概念 C#只有两种数据类型:值类型和引用类型 值类型在线程栈分配空间,引用类型在托管堆分配空间 值类型转为引用类型称成为装箱,引用类型转为值类型称为拆箱 以下是值类型和引用类型对照表 从上图可 ...

  8. 图解C#的值类型,引用类型,栈,堆,ref,out

    C# 的类型系统可分为两种类型,一是值类型,一是引用类型,这个每个C#程序员都了解.还有托管堆,栈,ref,out等等概念也是每个C#程序员都会接触到的概念,也是C#程序员面试经常考到的知识,随便搜搜 ...

  9. .NET中六个重要的概念:栈、堆、值类型、引用类型、装箱和拆箱 (转)

    作者: Edison Chou  来源: 博客园  发布时间: 2014-09-03 15:59  阅读: 318 次  推荐: 2   原文链接   [收藏]   原文作者:Shivprasad k ...

随机推荐

  1. codevs——1019 集合论与图论

    1019 集合论与图论  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Description 集合论与图论对于小松来说 ...

  2. spring boot 学习-创建方式

    spring boot是什么 spring boot 是一个快速开发框架,适合小白快速上手开发,它集成了很多优秀的和常用的第三方框架,它简化了xml配置,完全采用注解方式,内部集成了Tomcat.Je ...

  3. JSP的Cookie处理

    以下内容引用自http://wiki.jikexueyuan.com/project/jsp/Cookies-handling.html: Cookies是存储在客户端计算机的文本文件,保存各种跟踪目 ...

  4. openstack setup demo Image service

    Image service (glance)是openstack中管理vm image的service.本文包含以下内容: overview install overview glance包含以下部分 ...

  5. mybatis bug之resultmap缺少object-relation匹配参数password,造成设置密码不成功

    1.mybatis bug之resultmap缺少object-relation匹配参数password,造成设置密码不成功 在resultmap里没有设置user类中password属性和数据库表t ...

  6. 我的arcgis培训照片10

    来自:http://www.cnblogs.com/gisoracle/p/4297439.html

  7. Windows Server2008 R2 设置NAT 让Hyper-V连接Internet

    1.添加虚拟网卡,设置为内部,并且固定IP地址192.168.1.1 255.255.255.0 此为内网网卡 2.添加服务器角色:DHCP服务器,DNS服务器,网络策略和访问服务 3."网 ...

  8. ibatis 入门

     iBatis 简单介绍: iBatis 是apache 的一个开源项目.一个O/R Mapping 解决方式,iBatis 最大的特点就是小巧.上手非常快.假设不须要太多复杂的功能.iBatis ...

  9. Spring MVC 数据验证——validate编码方式

    1.导入jar包 validation-api-1.0.0.GA.jar这是比較关键的一个jar包,主要用于解析注解@Valid. hibernate-validator-4.3.2.Final.ja ...

  10. 软考之J2SE

    特别感谢软考让我如今就接触了神奇的java.曾经尽管真不知道java是个神马,看完马士兵的视频发现里面的东西并不陌生.有vb,c++,c#做基础加上这次的J2SE发现原来编程语言有非常多同样的特性.也 ...