3.1.3 值类型与引用类型的区别

值类型直接存储其值,而引用类型存储对其值的引用。这两种类型存储在内存的不同地方

从内存空间上看,值类型是在栈中操作,而引用类型则在堆中分配存储单元。栈在编译的时候就分配好内存空间,在代码中有栈的明确定义,而堆是程序运行中动态分配的内存空间,可以根据程序的运行情况动态地分配内存的大小。从内存空间上看,值类型是在栈中操作,而引用类型则在堆中分配存储单元。栈在编译的时候就分配好内存空间,在代码中有栈的明确定义,而堆是程序运行中动态分配的内存空间,可以根据程序的运行情况动态地分配内存的大小。

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

(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重写了Euals方法,从而对值类型按照实例的值来比较,而不是引用地址来比较。

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

【例3.6】下面以一段代码来详细讲解一下值类型与引用类型的区别,代码如下。(实例位置:光盘\mr\example\第3章\3.6)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Test04
{
    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 guru = 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("guru's name:{0}", guru.Name);//显示guru中的Name值
        }

    }
}

当改变了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,因此它们指向了同一块内存区域。既然是指向同一块区域,不管修改谁,另一个的值都会跟着改变,就像信用卡跟亲情卡一样,用亲情卡取了钱,与之关联的信用卡账上也会跟着发生变化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值