c# 值类型与引用类型的区别(含例子)

c# 值类型与引用类型的区别

参考资料:《C#程序设计》

1、首先我们先了解一下c#的基本数据类型包含哪些。
c#的数据类型可分为两种,分别是值类型和引用类型。关系如下图:
在这里插入图片描述
2、什么是值类型呢?
值类型直接存储数据值,它主要包括简单类型和复合类型两种,其中,简单类型是程序中使用的最基本类型,主要包括整数类型、浮点类型、布尔类型和字符类型等4种。值类型在栈中进行分配,因此效率很高,使用值类型主要目的是为了提高性能。值类型具有如下特性。
》值类型变量都存储在栈中。
》访问值类型变量时,一般都是直接访问其实例。
》每个值类型变量都有自己的数据副本,因此对一个值类型变量的操作不会影响其他变量。
》值类型变量不能为null,必须具有一个确定的值。

3、什么又是引用类型呢?
引用类型是构建C#应用程序的主要对象类型数据,引用类型的变量又称为对象,可存储对实际数据的引用。C#支持两个预定义的引用类型object和string。
在应用程序执行的过程中,引用类型使用new关键字创建对象实例,并存储在堆中。堆是一种由系统弹性配置的内存空间,没有特定大小及存活时间,因此可以被弹性地运用于对象的访问。
引用类型具有如下特征。
 必须在托管堆中为引用类型变量分配内存。
 在托管堆中分配的每个对象都有与之相关联的附加成员,这些成员必须被初始化。
 引用类型变量是由垃圾回收机制来管理的。
 多个引用类型变量可以引用同一对象,这种情形下,对一个变量的操作会影响另一个变量所引用的同一对象。
 引用类型被赋值前的值都是null。
所有被称为“类”的都是引用类型,主要包括类、接口、数组和委托等。例如:

Student student1=new Student();
Student student1=student1;

4、他们的区别是什么?
先上图,如下
在这里插入图片描述
值类型声明的变量int a1,a2的值是存储在栈中的,而引用类型则在栈中存储引用(地址/URL)指向内存堆中,把值存储在堆中相应的对象里。
4.1、概念上讲,值类型是直接存储值的,而引用类型则是对其引用的存储,存的一个地址,这个地址指向内存堆中相应的对象。
4.2、从内存空间上讲,值类型是在栈中操作,而引用类型则在堆中分配存储单元。栈在编译的时候就分配好内存空间,在代码中有栈的明确定义;而堆是程序运行中动态分配的内存空间,可以根据程序的运行情况动态地分配内存的大小。
4.3、因此,值类型总是在内存中占用一个预定义的字节数,而引用类型的变量则在堆中分配一个内存空间,这个内存空间包含的是对另一个内存位置的引用,这个位置是托管堆中的一个地址,即存放此变量实际值的地方。

5、例子
创建一个控制台应用程序,首先在程序中创建一个类stamp,该类中定义两个属Name和Age,其中Name属性为string引用类型,Age属性为int值类型;然后定义一个ReferenceAndValue类,该类中定义一个静态的Demonstration方法,该方法主要演示值类型和引用类型使用时,其中一个值变化时,另外的值是否变化;最后在Main方法中调用ReferenceAndValue类中的Demonstration方法输出结果。代码如下。

class Program
{
 static void Main(string[] args)
 {
 //调用ReferenceAndValue类中的Demonstration方法
 ReferenceAndValue.Demonstration();
 Console.ReadLine();
 }
}
public class stamp				//定义一个类
{
 public string Name { get; set; }		//定义引用类型
 public int Age { get; set; }			//定义值类型
}
public static class ReferenceAndValue		//定义一个静态类
{
 public static void Demonstration()		//定义一个静态方法
 {
 stamp Stamp_1 = new stamp { Name = "Premiere", Age = 25 };
 stamp Stamp_2 = new stamp { Name = "Again", Age = 47 };
 int age = Stamp_1.Age;			//获取值类型Age的值
 Stamp_1.Age = 22;			//修改值类型的值
 stamp Stamp_3 = Stamp_2;			//获取Stamp_2中的值
 Stamp_2.Name = "Again Amend";		//修改引用的Name值
 Console.WriteLine("Stamp_1's age:{0}", Stamp_1.Age);//显示Stamp_1中的Age值
 Console.WriteLine("age's value:{0}", age); //显示age值
 Console.WriteLine("Stamp_2's name:{0}", Stamp_2.Name);//显示Stamp_2中的Name值
 Console.WriteLine("Stamp_3's name:{0}", Stamp_3.Name);//显示Stamp_3中的Name值
 }
}
发布了6 篇原创文章 · 获赞 5 · 访问量 257

猜你喜欢

转载自blog.csdn.net/RuiHe_pan/article/details/105455435