在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. python 正则表达式 符号及其定义

    较好的文章https://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html

  2. BAT-运行程序

    @echo offrem copy C:\Users\Administrator\Desktop\0000\123.txt C:\Users\Administrator\Desktop\0000\45 ...

  3. Chip-seq peak annontation

    Chip-seq peak annontation Chip-seq peak annontation PeRl narrowPeak/boardPeak narrowPeak/boardPeak 是 ...

  4. sublime安装php_beautifier来格式化PHP代码

    注:如果你使用sublime3,php版本是5.6以上,推荐使用这个插件phpfmt 环境 操作系统:windows7 sublime版本:2.0.2 PHP安装路径: D:\wamp\bin\php ...

  5. pygame安装【在pycharm的IDE project下】

    pygame安装[在pycharm的IDE project下] 首先更新电脑的pip.exe[命令行下面] 然后进入IDE project ——>setting 中查找是否安装pygame 我的 ...

  6. String、StringBuffer、StringBuilder的区别和解析

    1.三个类之间的关系 他们都是通过字符数组来实现的,继承关系 String:字符串常量,不可变类 StringBuffer:字符串变量,可变类,线程安全 StringBuilder:字符串变量,可变类 ...

  7. Struts2(九.利用layer组件实现图片显示功能)

    1.layer前端组件介绍 layer是一款口碑极佳的web弹层组件,她具备全方位的解决方案,致力于服务各个水平段的开发人员,您的页面会轻松地拥有丰富而友好的操作体验. http://sentsin. ...

  8. Java反射篇学习笔记

    今天重新学习了java中的反射,写一篇学习笔记总结一下.代码基本都是照着两篇博客敲的: 参考一:   https://blog.csdn.net/sinat_38259539/article/deta ...

  9. 悲剧文本(Broken Keyboard (a.k.a. Beiju Text),UVA 11988)

    题目描述: 题目思路: 1.使用链表来重新定位各个字符 2.用数组实现链表 3.开一个数组list[i]来存储字符数组下一个字符的位置 #include <iostream> #inclu ...

  10. PHP计算两个已知经纬度之间的距离

    /** *求两个已知经纬度之间的距离,单位为千米 *@param lng1,lng2 经度 *@param lat1,lat2 纬度 *@return float 距离,单位千米 **/ privat ...