【C#】值传递、引用传递和string类型的不可变性

值类型和引用类型

值类型/引用类型包含有:

  • 值类型:int、double、bool、char、decimal、struct、enum
  • 引用类型:string、自定义类、数组、集合、object、接口

二者的区别:

  • 1、值类型和引用类型在内存上存储的地方不同:

    值类型存储在栈中,引用类型存储在堆中。

  • 2、在传递值类型和传递引用类型时,传递方式不同;

值类型的传递

值类型在传递的时候,传递的是值本身。

using System;

namespace 值传递和引用传递
{
    class Program
    {
        static void Main(string[] args)
        {
            int a = 1;
            int b = a;
            b = 2;
            Console.WriteLine("a={0}",a);
            Console.WriteLine("b={0}",b);
        }
    }
}

运行结果:

内存图:

在执行 int b=a; 时,在栈中开辟一块空间用于存储b,并将a中的值传给b。执行完 b=2; 后,b被赋予了新值,并覆盖了原来的值。根据输出结果,值传递后,b的值与a的值无关,互不影响。

引用类型的传递

注意:这里引用传递的运行结果放在string类型上会有所不同,这是因为string类型具有不可变性,string类型的不可变性在下文会有介绍。

引用类型传递的时候,传递的是对这个对象的引用(即存在堆中的地址)。

下面以自定义类(Person)来说明:

using System;

namespace 值传递和引用传递
{
    class Program
    {
        static void Main(string[] args)
        {
            Person p1 = new Person();
            p1.Name = "张三";
            Person p2 = p1;
            p2.Name = "李四";
            Console.WriteLine("p1.Name={0}",p1.Name);
            Console.WriteLine("p2.Name={0}", p2.Name);
        }
        public class Person
        {
            private string _name;
            public string Name
            {
                get { return _name; }
                set { _name = value; }
            }
        }
    }
}

运行结果:

内存图:

创建完成p1对象后,在堆上开辟一块存储空间,并将该存储空间的地址放在栈上,栈中这块空间的地址(标识)是p1。当p1对象传递给p2后,只是将对堆中的存储的引用(堆中的地址)复制一份传给p2,完成传递后p1和p2共同指向同一块内存,所以p1或p2中任意一个更改存储内容后,另一个也会改变。

string类型的不可变性

先按照上述“引用类型的传递”的思路来看string类型的传递:

using System;

namespace 值传递和引用传递
{
    class Program
    {
        static void Main(string[] args)
        {
            string a = "张三";
            string b = a;
            b = "李四";
            Console.WriteLine("a={0}", a);
            Console.WriteLine("b={0}", b);
        }
    }
}

运行结果:

从运行结果可以看出,string类型的传递和一般引用类型不同,这是因为string类型具有不可变性:

  • 当给一个字符串重新赋值以后,旧值并没有销毁,而是重新开辟了一块空间用于存储新值。

内存图:

在a赋值“张三”并传递给b后,根据“引用类型的传递”,a和b共同指向“张三”(如图:堆地址为10001)这块内存。但是,在b重新被赋值为“李四”后,堆中开辟一块空间存储“李四”,旧值“张三”依然存在,新值的堆地址(如图:堆地址为10002)赋给栈中b的存储以使b指向“李四”。至此,a和b就不再指向同一块堆空间了。故运行结果与一般引用类型有所不同。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值