值类型和引用类型的区别

c#支持两种类型:值类型(Value Types)和引用类型(Reference Types),值类型包括简单类型(如:char、int和float等等)、枚举类型(Enum Types)和结构类型(Struct Types)、引用类型包括类类型、接口类型、委托类型和数组类型。
     值类型与引用类型的不同点在于:值类型的变量直接包含它们的数据,而引用类型的变量则把引用存储到对象中。引用类型的两个变量可以引用同一个对象。这样,对一个变量的操作就可能影响另一个变量所引用的对象。值类型的每一个变量都具有它们自己的数据拷贝,因此对一个变量的操作不可能影响到另一个变量。 

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

namespace ConsoleApplication1
{
    class Person
    {
        public int Blood = 10;   
    }

    class Program
    {
        public static void Add(int x)
        {
            x += 10;
            Console.WriteLine("值类型当参数被传递并修改之后:"+x);
        }

        public static void Add(Person person)
        {
            person.Blood += 10;
            Console.WriteLine("引用类型当参数被传递并修改之后:" + person.Blood);
        }

        static void Main(string[] args)
        {
            //值类型变量
            int i = 10;

            Console.WriteLine("i的原值:" + i);
            Add(i);
            Console.WriteLine("但是i的值并没有因为函数的修改而修改:" + i);

            //引用类型变量
            Person person = new Person();

            Console.WriteLine("Blood的原值:" + person.Blood);
            Add(person);
            Console.WriteLine("但是Blood的值因为函数的修改而修改:" + person.Blood);

            //值类型和引用类型的区别,就在于当函数参数传递的时候.
            //值类型是把自己的值复制一份传递给别的函数操作.无论复制的值怎么被改变.其自身的值是不会改变的
            //而引用类型是把自己的内存地址传递给别的函数操作.操作的就是引用类型值的本身.所以值被函数改变了.
            //这就是传值和传址的区别

            Console.ReadLine();
        }
    }
}

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

namespace ConsoleApplication1
{
    class Person
    {
        public int Blood = 10;   
    }

    class Program
    {
        public static void Add(int x)
        {
            x += 10;
            Console.WriteLine("值类型当参数被传递并修改之后:"+x);
        }

        public static void Add(Person person)
        {
            person.Blood += 10;
            Console.WriteLine("引用类型当参数被传递并修改之后:" + person.Blood);
        }

        static void Main(string[] args)
        {
            //值类型变量
            int i = 10;

            Console.WriteLine("i的原值:" + i);
            Add(i);
            Console.WriteLine("但是i的值并没有因为函数的修改而修改:" + i);

            //引用类型变量
            Person person = new Person();

            Console.WriteLine("Blood的原值:" + person.Blood);
            Add(person);
            Console.WriteLine("但是Blood的值因为函数的修改而修改:" + person.Blood);

            //值类型和引用类型的区别,就在于当函数参数传递的时候.
            //值类型是把自己的值复制一份传递给别的函数操作.无论复制的值怎么被改变.其自身的值是不会改变的
            //而引用类型是把自己的内存地址传递给别的函数操作.操作的就是引用类型值的本身.所以值被函数改变了.
            //这就是传值和传址的区别

            Console.ReadLine();
        }
    }
}

一个具有值类型(value type)的数据存放在内的一个变量中。即是在栈中分配内存空间,直接存储所包含的值,其值就代表数据本身。值类型的数据具有较快的存取速度

一个具有引用类型(reference type)的数据并不驻留在栈中,而是存储于中。即是在堆中分配内存空间,不直接存储所包含的值,而是指向所要存储的值,其值代表的是所指向的地址。当访问一个具有引用类型的数据时,需要到栈中检查变量的内容,该变量引用堆中的一个实际数据。引用类型的数据比值类型的数据具有更大的存储规模和较低的访问速度

 
问     题值 类 型引 用 类 型
这个类型分配在哪里? 分配在栈上 分配在托管堆上
变量是怎么表示的? 值类型变量是局部复制 引用类型变量指向被分配得实例所占的内存
基类型是什么? 必须继承自System.ValueType 可以继承自除了System.ValueType以外的任何类型,只要那个类型不是sealed的
这个类型能作为其他类型的基类吗? 不能。值类型是密封的,不能被继承 是的。如果这个类型不是密封的,它可以作为其他类型的基类
默认的参数传递是什么? 变量是按值传递的(也就是,一个变量的副本被传入被调用的函数) 变量是按引用传递(例如,变量的地址传入被调用的函数)
这个类型能重写System.Object.Finalize()吗? 不能。值类型不好放在堆上,因此不需要被终结。 可以间接地重写
我可以为这个类型定义构造函数吗? 是的,但是默认的构造函数被保留(也就是自定义构造函数必须全部带有参数) 当然!
这个类型的变量什么时候消亡? 当它们越出定义的作用域时。

当托管堆被垃圾回收时。

 顺便看一下下面的代码,看看运行的结果

  public class Test
    {
        public int num;
        public Test(int x)
        {
            this.num = x;
        }
        public void ChangeNum(Test x)
        {
           
            x = new Test(100);
           
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
           Test ts = new Test(10);
            ts.ChangeNum(ts);
           Console.WriteLine(ts.num);
            Console.ReadKey();
        }
    }

大家知道结果了吗。

运行的结果是10

原文地址:https://www.cnblogs.com/love828/p/3221177.html