在C#中,值类型和引用类型是相当重要的两个概念,必须在设计类型的时候就决定类型实例的行为。如果在编写代码时不能理解引用类型和值类型的区别,那么将会给代码带来不必要的异常。很多人就是因为没有弄清楚这两个概念从而在编程过程中遇到了很多问题,在这里博主浅谈对值类型和引用类型的认识。

首先从概念上看,值类型直接存储其值,而引用类型存储对其值的引用。从而这两种类型存储在内存的不同地方。

其次从内存空间上看,值类型是在栈中操作,而引用类型则在堆中分配存储单元。

栈在编译的时候就分配好内存空间,在代码中有栈的明确定义,而堆是程序运行中动态分配的内存空间,可以根据程序的运行情况动态地分配内存的大小。因此,值类型总是在内存中占用一个预定义的字节数。而引用类型的变量则在栈中分配一个内存空间,这个内存空间包含的是对另一个内存位置的引用,这个位置是托管堆中的一个地址,即存放此变量实际值的地方。

也就是说值类型相当于现金,要用就直接用,而引类型相当于存折,要用得先去银行取。

但值类型在栈上分配内存,而引用类型在托管堆上分配内存,只是一种笼统的说法。下面对其进行详细描述。

(1)对于值类型的实例,如果作为方法中的局部变量,则被创建在线程栈上;如果该实例作为类型的成员,则作为类型成员的一部分,连同其他类型字段存放在托管堆上。

每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值。例如:

int i = new int(); 

等价于:

Int32 i = new Int32(); 

等价于:

int i = 0; 

等价于:

Int32 i = 0; 

使用new运算符时,将调用特定类型的默认构造函数并对变量赋以默认值。在上例中,默认构造函数将值0赋给了i。

说明:C#的所有值类型均隐式派生自System.ValueType,而System.ValueType直接派生于System.Object。即System.ValueType本身是一个类类型,而不是值类型。其关键在于ValueType重写了Equals方法,从而对值类型按照实例的值来比较,而不是引用地址来比较。

(2)引用类型的实例创建在托管堆上。

下面以一段代码来详细讲解一下值类型与引用类型的区别

 1    namespace Test
2 {
3 class Program
4 {
5 static void Main(string[] args)
6 {
7 //调用ReferenceAndValue类中的Demonstration方法
8 ReferenceAndValue.Demonstration();
9 Console.ReadLine();
10 }
11 }
12 public class stamp //定义一个类
13 {
14 public string Name { get; set; } //定义引用类型
15 public int Age { get; set; } //定义值类型
16 }
17 public static class ReferenceAndValue //定义一个静态类
18 {
19 public static void Demonstration() //定义一个静态方法
20 {
21 stamp Stamp_1 = new stamp { Name = "Premiere", Age = 25 }; //实例化
22 stamp Stamp_2 = new stamp { Name = "Again", Age = 47 }; //实例化
23 int age = Stamp_1.Age; //获取值类型Age的值
24 Stamp_1.Age = 22; //修改值类型的值
25 stamp guru = Stamp_2; //获取Stamp_2中的值
26 Stamp_2.Name = "Again Amend"; //修改引用的Name值
27 Console.WriteLine("Stamp_1's age:{0}", Stamp_1.Age); //显示Stamp_1中的Age值
28 Console.WriteLine("age's value:{0}", age); //显示age值
29 Console.WriteLine("Stamp_2's name:{0}", Stamp_2.Name); //显示Stamp_2中的Name值
30 Console.WriteLine("guru's name:{0}", guru.Name); //显示guru中的Name值
31 }
32 }
33 }

通过运行上面一段程序之后我们可以看出,当改变了Stamp_1.Age的值时,age并没有跟着变,但在改变了anders.Name的值后,guru.Name却跟着变了,这就是值类型和引用类型的区别。在声明age值类型变量时,将 Stamp_1.Age的值赋给它,这时,编译器在栈上分配了一块空间,然后把Stamp_1.Age的值填进去,二者没有任何关联,就像在计算机中复制文件一样,只是把Stamp_1.Age的值拷贝给age了。而引用类型则不同,在声明guru时把Stamp_2赋给它,前面说过,引用类型包含的只是堆上数据区域地址的引用,其实就是把Stamp_2的引用也赋给guru,因此它们指向了同一块内存区域。既然是指向同一块区域,不管修改谁,另一个的值都会跟着改变,就像信用卡跟亲情卡一样,用亲情卡取了钱,与之关联的信用卡账上也会跟着发生变化。

【.Net】浅谈C#中的值类型和引用类型的更多相关文章

  1. 浅谈C#中的值类型和引用类型

    在C#中,值类型和引用类型是相当重要的两个概念,必须在设计类型的时候就决定类型实例的行为.如果在编写代码时不能理解引用类型和值类型的区别,那么将会给代码带来不必要的异常.很多人就是因为没有弄清楚这两个 ...

  2. C# 中的值类型和引用类型

    原文 C# 中的值类型和引用类型 值类型(value type):int,long,float,double,decimal,char,bool 和 struct 统称为值类型.值类型变量声明后,不管 ...

  3. C++ : 从栈和堆来理解C#中的值类型和引用类型

    C++中并没有值类型和引用类型之说,标准变量或者自定义对象的存取默认是没有区别的.但如果深入地来看,就要了解C++中,管理数据的两大内存区域:栈和堆. 栈(stack)是类似于一个先进后出的抽屉.它的 ...

  4. C#中的值类型和引用类型,深拷贝,浅拷贝

    from https://www.jianshu.com/p/2d27b06e253f 一.C#中的值类型和引用类型 概念 值类型直接存储其值. 引用类型存储对值的引用. 说起来有些拗口,其本质是Va ...

  5. .NET中的值类型与引用类型

    .NET中的值类型与引用类型 这是一个常见面试题,值类型(Value Type)和引用类型(Reference Type)有什么区别?他们性能方面有什么区别? TL;DR(先看结论) 值类型 引用类型 ...

  6. Windows Phone 开发起步之旅之二 C#中的值类型和引用类型

    今天和大家分享下本人也说不清楚的一个C#基础知识,我说不清楚,所以我才想把它总结一下,以帮助我自己理解这个知识上的盲点,顺便也和同我一样不是很清楚的人一起学习下.  一说起来C#中的数据类型有哪些,大 ...

  7. C#中对值类型和引用类型的一点认识

    区别值类型和引用类型的重要一点就是值类型赋值的时候是给出一块内存空间,空间里放下要赋给值类型的值.而引用类型是开辟一块内存空间,空间里放下的是要赋给引用类型值的指向地址. 就像一个是复制了银行卡里的现 ...

  8. js中的值类型和引用类型的区别

    1.JavaScript中的变量类型有哪些? (1)值类型(基本类型):字符串(String).数值(Number).布尔值(Boolean).Undefined.Null  (这5种基本数据类型是按 ...

  9. C#中的值类型、引用类型,代码告诉你他是什么类型。

    C#代码告诉你这是什么类型. using System; using System.Collections.Generic; using System.Linq; using System.Text; ...

随机推荐

  1. break和continue使用

    前面讲的循环,这里就是控制循环的东西 break其实在我们学习switch判断的时候就是用到了 break:代表跳出整个循环 continue和break的用法差不多 continue:代表只跳出当前 ...

  2. 北京Uber优步司机奖励政策(4月9日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  3. 北京Uber优步司机奖励政策(1月26日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  4. CSS3 子节点选择器

    CSS3中新增了几个子元素选择器,大大提高了开发者的开发效率.之前有些要通过为一个个子元素添加class,或者js实现才能实现的效果.现在可以很方便的用选择器实现. 这些新的样式已被现代浏览器及IE9 ...

  5. Ruby学习系列一,基本认识

    安装Ruby后,打开命令行,先来看下Ruby的版本. ruby -v ,如果看到类似 ruby 1.9.3p392.... ,说明我们的Ruby安装成功了. 然后我们输入 irb ,进入Ruby的交互 ...

  6. TW实习日记:第23天

    主要的项目已经在修改一些细节以提高用户体验的阶段了,所以并不是太忙,主要就是对样式和一些细节修修改改.然后下午帮助同事的新项目做了一个功能点,主要就是调通接口就行,因为参数巨多,所以总要和网端那边的后 ...

  7. vue-router爬坑记

    简介 因为我们用Vue开发的页面是单页面应用,就相当于只有一个主的index.html,这时候我们就不能使用a标签来进行页面的切换了,所以这时候我们今天的主角Vue-Router就闪亮的登场了 Vue ...

  8. post接口_form表单上传

    上传文件的本质是浏览器读取本地文件的内容,以二进制数据方式传输到服务端,服务端新建一个文件,将获取到的数据复制到文件中 LR中上传操作可以通过web_submit_data函数实现,支持录制要点:we ...

  9. 如何处理 jQuery $(window).resize() 中的方法被多次执行的小问题

    引言: 估计很多同志们在编写浏览器resize()的方法时,都会遇到这样的情况: 当拖动浏览器的边角时,页面中的一些效果随浏览器大小的改变而触发,这一过程开始到结束,resize() 中的方法被执行了 ...

  10. Python基础 之 tuple类-元组 和 dict类-字典

    tuple 元组 一.tuple 类的基本属性 1.元组,有序:元素不可被修改,不能被增加或者删除tuple类 tu = (111,22,33,44) 一般写元组的时候,推荐在最后加入,和类方法进行区 ...