C# - 值类型、引用类型&走出误区,容易错误的说法

1. 值类型与引用类型小总结

1)对于引用类型的表达式(如一个变量),它的值是一个引用,而非对象。

2)引用就像URL,是允许你访问真实信息的一小片数据。

3)对于值类型的表达式,它的值是实际的数据。

4)有时,值类型比引用类型更有效,有时恰好相反。

5)引用类型的对象总是在堆上,值类型的值既可能在栈上,也可能在堆上,具体取决于上下文。

6)引用类型作为方法参数使用时,参数默认是以‘值传递’方式来传递的,但值本身是一个引用。

7)值类型的值会在需要引用类型的行为时装箱;拆箱则是相反的过程。

2. 误区一 结构是轻量级的类

这个误解存在着多种形式。有人认为值类型不能或不应有方法或有其他意义的行为:它们应作为简单的数据转移类型来使用,只应该有public字段或简单的属性。对于这种说法,一个非常典型的反例就是Datetime类型。DateTime作为值类型来提供是很有道理的,因为它非常适合作为和数字或字符相似的一个基本单位来使用。另外,它也理应被赋予对它的值执行计算的能力。换个角度来看这个问题,是数据转移类型一般都是引用类型。总之,具体应该如何决定,应取决于需要的是值类型的语义,还是引用类型的语义,而不是取决于这个简单类型与否。

还有一些人认为值类型之所以显得比引用类型‘轻’,是因为性能,事实是在某些情况下,值类型很能‘干’:它们不需要垃圾回收,(除非被装箱)不会因类型标识而产生开销,也不需要解引用。但在其他方面,引用类型显得更‘能干’:在传递参数、赋值、将值返回和执行类似的操作时,只需复制4或8字节(需要看运行的是32位或是64位CLR),而不是复制全部数据。假定ArrayList是一个所谓‘纯的’值类型,那么将一个ArrayList表达式传给一个方法时,就得复制它的所有数据!几乎在所有情况下,性能问题都不是根据这种判断来决定的。瓶颈从来都不是想当然的,在你根据性能进行设计之前,需要衡量不同的选择。

值得注意的是,将这两者相结合也不能解决问题:类型(不管是类还是结构)拥有多少方法并不重要,每个实例所占用的内存不会受到影响。(代码本身会消耗内存,但这只会发生一次,而不是每个实例都发生)

3. 误区二 引用类型保存在堆上,值类型保存在栈上

这个误区主要应归咎于转述这句话的人根本没有动脑筋。这一部分是正确的,引用类型的实例总是在堆上创建的。但第二部分就有问题了。

前面讲述过,变量的值是在它声明的位置存储的。所以,假定一个类中又一个int类型的实例变量,那么在这个类中的任何对象中,该变量的值总是和对象中的其他数据在一次,也就是在堆上。只有局部变量(方法内部声明的变量)和方法参数在栈上。对于C#2或以上版本,很多局部变量并不完全存放在栈中。

4. 误区三 对象在C#中默认是通过引用传递的

这或许是传播得最广的一个误区了。统一说这句话的人一般知道C#实际的行为是什么,但不知道‘引用传递pass by reference’的真正意思是什么。可惜,那些真正知道引用传递是什么意思的人,在听到这句话时会被完全搞糊涂。

‘引用传递’的正式定义相当复杂,要涉及坐值(1-values)和类似的计算机科学术语。但最重要的一点是,假如以引用传递的方式来传送一个变量,那么调用的方法可以通过更改其参数值,来改变调用者的变量值。现在请记住,引用类型变量的值是引用,而不是对象本身。不需要按引用来传递参数本身,就可以更改该参数的引用的那个对象的内容。例如,下面的方法更改了相关对象StringBuilder的内容,但调用者的表达式引用的仍然是之前的那个对象:

        public void AppendHello(StringBuilder builder){builder.Append("Hello");}

调用这个方法时,参数值(对StringBuilder的一个引用)是以值传递pass by value 的方式传递的。如果想在方法内部更改builder变量的值,如执行builder=null 语句,调用者看不见这个改变,刚好跟错误认识相反。

有趣的是,这种错误说法中,不仅引用传递的说法有误,而且 对象传递的说法也存在问题。无论引用传递还是值传递,永远不会传递对象本身。涉及一个引用类型时,要么以引用传递的方式传递变量,要么以传值的方式传递参数值(引用)。最起码,这回答了‘当null作为一个传值参数的值来使用时会发生什么’的问题。假如传递的是对象,这是就会出问题,因为没有一个对象可供传递!相反,null引用会采用和其他引用一样的值传递方式传递。

可以关注本人的公众号,多年经验的原创文章共享给大家。

posted on 2017-01-06 16:45 alun-chen 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/alunchen/p/6256903.html

C# - 值类型、引用类型走出误区,容易错误的说法相关推荐

  1. 变量/值类型/引用类型/常量/枚举

    变量 声明语法 datatype identifier; 如:int i; //声明一个int类型的变量,但是在没有初始化之前编译器不允许使用该变量 同时声明多个 int a,b;//同时声明两个in ...

  2. javascript基本数据类型与值类型引用类型说明

    DEMO: http://sources.ikeepstudying.com/jsdata/ 摘要:本文主要讲了javascript中的基本数据类型,以及值类型和引用类型的区别与使用 一.基本数据类型 ...

  3. 走出误区,老杨命运发生了转折

    杨先生,39岁,来自青海西宁,出生于高原地区.杨先生是一位货车司机,常年奔波在青海.新疆两地.因路途遥远,交通不便,几乎常年在车上生活.在2010年一次远征的路上,杨先生发现自己的眼睛睁起来很费劲,而 ...

  4. C#值类型-引用类型

    转换-值类型-引用类型-预定义分类表 转换 C#里,兼容的实例间可以进行相互转换 转换总是从一个值转换成一个新的值 隐式转换:隐式转换是自动发生的 显式转换:显式转换是手动操作的 长整型转换成整型的时 ...

  5. 值类型 引用类型 堆栈 堆 之 异想

    看了很多值类型 和 引用类型的文章(谷歌能搜索出来的) 看了越多疑问越大,而这些资料中没有具体的说明. 问题: 1.堆栈 和 堆 分别存于计算机的哪个硬件(CPU缓存,内存,硬盘)? 2.为什么只有值 ...

  6. iOS开发-Swift进阶之值类型 引用类型!

    本文主要介绍为什么结构体是值类型,类是引用类型 值类型 图片看不了请前往简书 前提:需要了解内存五大区,,如下所示 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XFI ...

  7. 关于C#值类型,引用类型,值传递,引用传递

    说到参数传递,必须得弄清值类型和引用类型: (为了容易表达,我暂且命名存放在堆中的内容为堆中对象,存放在栈上的内容为栈中对象.) 值类型存放在栈中,直接访问.如果有:int a=0;int b=a;就 ...

  8. C#基础_值类型引用类型(十一)

    值类型和引用类型: 值类型包括:byte,short,int,long,char,float,double,bool,struct结构 引用类型包括:类类型,接口类型和数组 等. 值类型和引用类型特点 ...

  9. 6个重要的.NET概念:栈,堆,值类型,引用类型,装箱,拆箱

    引言 本篇文章主要介绍.NET中6个重要的概念:栈,堆,值类型,引用类型,装箱,拆箱.文章开始介绍当你声明一个变量时,编译器内部发生了什么,然后介绍两个重要的概念:栈和堆:最后介绍值类型和引用类型,并 ...

最新文章

  1. java office 集成开发_Office文件格式突变,促使Java和Office更完美集成
  2. 中小型商业银行的软件安全测试之道
  3. 【算法入门】用Python手写五大经典排序算法,看完这篇终于懂了!
  4. SQLSetEnvAttr
  5. oracle odbc 设置_Oracle删除不干净怎么办?
  6. bzoj 4260 REBXOR —— Trie树
  7. Android集成JPush(极光推送)
  8. oracle自定义长度异常,Oracle 自定义wmsys.wm_concat 避免长度限制
  9. 支付宝生活号,同时出现俩网址,到底哪个真哪个假?
  10. 斗鱼 Juno 监控中心的设计与实现
  11. Vue项目使用v-drag实现拖拽功能
  12. 为什么蚕宝宝很有钱?
  13. android 解析json 日期格式,处理Json数据中的日期类型.如/Date(1415169703000)/格式
  14. IDEA添加oracle数据库时不显示数据表
  15. 前端 js 微信 支付二维码
  16. 如何做Unity手游性能优化的
  17. html设置横线中间的字,CSS伪元素before,after制作左右横线中间文字效果
  18. 高博视觉SLAM十四讲思维导图分享
  19. RPA 的优点与缺点
  20. PR2019 (二)比较基本

热门文章

  1. VC++ 单文档项目显示打开的文件
  2. Kubernetes List-Watch
  3. Cannot add or update a child row:
  4. WebRTC详解-zz
  5. Java基础知识强化之IO流笔记42:IO流总结(图解)
  6. Android -- isInEditMode
  7. mysql 事物隔离级别详解
  8. Linux入门-shell使用技巧
  9. 以太网口差分电平_以太网接口学习笔记
  10. 【DIY】震精!他居然用esp8266做出掌上游戏机......恐龙跑酷游戏还能这样玩!请广泛转发!...