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引用会采用和其他引用一样的值传递方式传递。
可以关注本人的公众号,多年经验的原创文章共享给大家。

C# - 值类型、引用类型&走出误区,容易错误的说法的更多相关文章
- 数往知来C#之接口 值类型与引用类型 静态非静态 异常处理 GC垃圾回收 值类型引用类型内存分配<四>
C# 基础接口篇 一.多态复习 使用个new来实现,使用virtual与override -->new隐藏父类方法 根据当前类型,电泳对应的方法(成员) -->override ...
- 30天C#基础巩固-----值类型/引用类型,泛型,空合并操作符(??),匿名方法
一:值类型/引用类型的区别 值类型主要包括简单类型,枚举类型,和结构体类型等,值类型的实例通常被分配在线程堆栈上面变量保存的内容是实例数据本身.引用类型被分配在托管堆上,变量保存的是地址.引 ...
- 深入C#内存管理来分析值类型&引用类型,装箱&拆箱,堆栈几个概念组合之间的区别
C#初学者经常被问的几道辨析题,值类型与引用类型,装箱与拆箱,堆栈,这几个概念组合之间区别,看完此篇应该可以解惑. 俗话说,用思想编程的是文艺程序猿,用经验编程的是普通程序猿,用复制粘贴编程的是2B程 ...
- C# 值类型 引用类型
CLR 定义了两种类型,ReferenceTypes引用类型 和 ValueTypes 值类型.我们定义的各种Class都是引用类型,而我们用的decimal int 之类是值类型. 他们有什么区别呢 ...
- (值类型引用类型)和null的关系
1.null null表示变量没有指向任何对象. 2.值类型 包括 bool.结构体.枚举.int.double.float等等 .在.NET中值类型都继承自ValueType. 3. 引 ...
- JAVASCRIPT数据类型(值类型-引用类型-类型总览)
值类型:也称为原始数据或原始值(primitive value). 这类值存储在栈(stack)中,栈是内存中一种特殊的数据结构,也称为线性表,栈按照后进先出的原则存储数据,先进入的数据被压入栈底,最 ...
- 深入理解C#学习笔记之走出误区
通过学习深入理解C#这本书,发现自己对于C#这门语言一直存在着三个误区. 第一个误区:结构是轻量级的类: 我一直认为值类型不应该具有方法或其他有意义的行为,它们只应该具有一些简单的属性.但书中总结了一 ...
- js的基础(平民理解的执行上下文/调用堆栈/内存栈/值类型/引用类型)
与以前的切图比较,现在的前端开发对js的要求似乎越来越高,在开发中,我们不仅仅是要知道如何运用现有的框架(react/vue/ng), 而且我们对一些基础的知识的依赖越来越大. 现在我们就用平民的方法 ...
- c#值类型引用类型第一章
概要 本篇文章主要简单扼要的讲述值类型和引用类型更进阶的理解和使用.如果希望更多的了解和技术讨论请记得看文章末尾,望各位看官多多支持多多关注,关注和支持是我更新文章的最大动力.在这里谢谢大家.温馨提示 ...
随机推荐
- 读书笔记:JavaScript DOM 编程艺术(第二版)
读完还是能学到很多的基础知识,这里记录下,方便回顾与及时查阅. 内容也有自己的一些补充. JavaScript DOM 编程艺术(第二版) 1.JavaScript简史 JavaScript由Nets ...
- Partition2:对表分区
在SQL Server中,普通表可以转化为分区表,而分区表不能转化为普通表,普通表转化成分区表的过程是不可逆的,将普通表转化为分区表的方法是: 在分区架构(Partition Scheme)上创建聚集 ...
- 如何在nuget上传自己的包+搭建自己公司的NuGet服务器(新方法)
运维相关:http://www.cnblogs.com/dunitian/p/4822808.html#iis 先注册一个nuget账号https://www.nuget.org/ 下载并安装一下Nu ...
- Win10 IIS本地部署MVC网站时不能运行?
异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 部署后出现这个错误: 打开文件目录后发现是可以看见目录的,静态页面也是可以打开的 ...
- .Net 大型分布式基础服务架构横向演变概述
一. 业务背景 构建具备高可用,高扩展性,高性能,能承载高并发,大流量的分布式电子商务平台,支持用户,订单,采购,物流,配送,财务等多个项目的协作,便于后续运营报表,分析,便于运维及监控. 二. 基础 ...
- 【原创分享·微信支付】 C# MVC 微信支付教程系列之公众号支付
微信支付教程系列之公众号支付 今天,我们接着讲微信支付的系列教程,前面,我们讲了这个微信红包和扫码支付.现在,我们讲讲这个公众号支付.公众号支付的应用环境常见的用户通过公众号,然后再通 ...
- SDWebImage源码解读_之SDWebImageDecoder
第四篇 前言 首先,我们要弄明白一个问题? 为什么要对UIImage进行解码呢?难道不能直接使用吗? 其实不解码也是可以使用的,假如说我们通过imageNamed:来加载image,系统默认会在主线程 ...
- MFC中成员变量的声明顺序与析构顺序
第一次用博客,第一篇随笔,就写今天遇到的一个问题吧. 在VS2008的MFC对话框程序,窗口成员变量的声明顺序与其析构顺序相反,即,先声明的变量后析构,后声明的变量先析构.未在其他模式下测试. cla ...
- java中易错点(一)
由于replaceAll方法的第一个参数是一个正则表达式,而"."在正则表达式中表示任何字符,所以会把前面字符串的所有字符都替换成"/".如果想替换的只是&qu ...
- Atitit.attilax软件研发与项目管理之道
Atitit.attilax软件研发与项目管理之道 1. 前言4 2. 鸣谢4 3. Genesis 创世记4 4. 软件发展史4 5. 箴言4 6. 使徒行传 4 7. attilax书 4 8. ...