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# - 值类型、引用类型&走出误区,容易错误的说法的更多相关文章

  1. 数往知来C#之接口 值类型与引用类型 静态非静态 异常处理 GC垃圾回收 值类型引用类型内存分配<四>

    C# 基础接口篇 一.多态复习 使用个new来实现,使用virtual与override    -->new隐藏父类方法 根据当前类型,电泳对应的方法(成员)    -->override ...

  2. 30天C#基础巩固-----值类型/引用类型,泛型,空合并操作符(??),匿名方法

    一:值类型/引用类型的区别      值类型主要包括简单类型,枚举类型,和结构体类型等,值类型的实例通常被分配在线程堆栈上面变量保存的内容是实例数据本身.引用类型被分配在托管堆上,变量保存的是地址.引 ...

  3. 深入C#内存管理来分析值类型&引用类型,装箱&拆箱,堆栈几个概念组合之间的区别

    C#初学者经常被问的几道辨析题,值类型与引用类型,装箱与拆箱,堆栈,这几个概念组合之间区别,看完此篇应该可以解惑. 俗话说,用思想编程的是文艺程序猿,用经验编程的是普通程序猿,用复制粘贴编程的是2B程 ...

  4. C# 值类型 引用类型

    CLR 定义了两种类型,ReferenceTypes引用类型 和 ValueTypes 值类型.我们定义的各种Class都是引用类型,而我们用的decimal int 之类是值类型. 他们有什么区别呢 ...

  5. (值类型引用类型)和null的关系

    1.null    null表示变量没有指向任何对象. 2.值类型    包括 bool.结构体.枚举.int.double.float等等 .在.NET中值类型都继承自ValueType. 3. 引 ...

  6. JAVASCRIPT数据类型(值类型-引用类型-类型总览)

    值类型:也称为原始数据或原始值(primitive value). 这类值存储在栈(stack)中,栈是内存中一种特殊的数据结构,也称为线性表,栈按照后进先出的原则存储数据,先进入的数据被压入栈底,最 ...

  7. 深入理解C#学习笔记之走出误区

    通过学习深入理解C#这本书,发现自己对于C#这门语言一直存在着三个误区. 第一个误区:结构是轻量级的类: 我一直认为值类型不应该具有方法或其他有意义的行为,它们只应该具有一些简单的属性.但书中总结了一 ...

  8. js的基础(平民理解的执行上下文/调用堆栈/内存栈/值类型/引用类型)

    与以前的切图比较,现在的前端开发对js的要求似乎越来越高,在开发中,我们不仅仅是要知道如何运用现有的框架(react/vue/ng), 而且我们对一些基础的知识的依赖越来越大. 现在我们就用平民的方法 ...

  9. c#值类型引用类型第一章

    概要 本篇文章主要简单扼要的讲述值类型和引用类型更进阶的理解和使用.如果希望更多的了解和技术讨论请记得看文章末尾,望各位看官多多支持多多关注,关注和支持是我更新文章的最大动力.在这里谢谢大家.温馨提示 ...

随机推荐

  1. 《JavaScript权威指南》学习笔记 第七天 DOM操作

    由衷的觉得,随着IT技术的广泛的运用,个人电脑以及智能手机的使用,信息的获取与传播更为简单.但是我们获取有用信息的难度相反是越来越大了,想要保持住自己的注意力越来越难了.除了吃饭睡觉,我的精力都在电脑 ...

  2. JavaScript 函数参数传递到底是值传递还是引用传递

    tips:这篇文章是听了四脚猫的js课程后查的,深入的理解可以参看两篇博客: JavaScript数据类型--值类型和引用类型 JavaScript数据操作--原始值和引用值的操作本质 在传统的观念里 ...

  3. Prince2的七大原则(6)

    Prince2科普_Prince2的七大原则(6) 按照惯例我们先来回顾一下,PRINCE2七大原则分别是指:持续的业务验证,经验学习,角色与责任,按阶段管理,例外管理,关注产品,剪裁. 今天讲第六个 ...

  4. 使用SQL Server 2014内存数据库时需要注意的地方

    作者 王枫发布于2014年7月4日 本文从产品设计和架构角度分享了Microsoft内存数据库方面的使用经验,希望你在阅读本文之后能够了解这些新的对象.概念,从而更好地设计你的架构. 内存数据库,指的 ...

  5. Java Executor 框架学习总结

    大多数并发都是通过任务执行的方式来实现的.一般有两种方式执行任务:串行和并行. class SingleThreadWebServer { public static void main(String ...

  6. 浅谈JavaScript函数

    JavaScript作为一种基于对象(非严格面向对象)的语言,函数在JS中的地位非同一般:用函数声明类和对象.甚至函数本身也是对象. 一.函数的三种声明方式辨析. 1.function命令 funct ...

  7. Android-Ant自动编译打包android项目 -- 2 ----签名与渠道包

    上篇介绍了怎么使用ant自动编译打包现有的android项目,这篇将继续介绍如果如何在ant打包应用的时候加入签名信息以及自动打包渠道包. 1. 加入签名信息: 在项目的根目录下建一个ant.prop ...

  8. Unity3D合并着色器

    unity 3d倒每次模型更多的是一种着色器.我可以拥有这些车型共享的地图想分享一个着色器.所以每次删除,然后附加,很麻烦.如何才能合并这些着色器? 采纳TexturePacking对 1.遍历gam ...

  9. Light OJ 1266 - Points in Rectangle

    题目 Link 就是查询矩形内有多少个点. 分析 二维树状数组维护就好了,. Code #include <bits/stdc++.h> const int maxn = 1000 + 1 ...

  10. 微服务框架——SpringCloud(四)

    1.Spring Cloud Config 分布式配置 a.Config服务器 ①新建springboot项目,依赖选择Config Server ②pom文件关键依赖 <parent> ...