C#值类型和引用类型

什么是值类型,什么是引用类型

值类型就是直接存储其值
引用类型存储对其值的引用

引用类型:基类为Objcet
值类型:均隐式派生自System.ValueType

  • 值类型:
    byte,short,int,long,float,double,decimal,char,bool 和 struct 统称为值类型。
  • 引用类型:
    string 和 class ,interface,array ,delegate统称为引用类型。

区别

  • 值类型变量声明后,不管是否已经赋值,编译器为其分配内存。
  • 引用类型当声明一个类时,只在栈中分配一小片内存用于容纳一个地址,而此时并没有为其分配堆上的内存空间。当使用 new 创建一个类的实例时,分配堆上的空间,并把堆上空间的地址保存到栈上分配的小片空间中。

对象的传递

将值类型的变量赋值给另一个变量(或者作为参数传递),会执行一次值复制。将引用类型的变量赋值给另一个引用类型的变量,它复制的值是引用对象的内存地址,因此赋值后就会多个变量指向同一个引用对象实例。

代码示例

int v1 = 0;
            int v2 = v1;
            v2 = 100;
            Console.WriteLine("v1=" + v1); //输出:v1=0
            Console.WriteLine("v2=" + v2); //输出:v2=100

            User u1=new User();
            u1.Age = 0;
            User u2 = u1;
            u2.Age = 100;
            Console.WriteLine("u1.Age=" + u1.Age); //输出:u1.Age=100
            Console.WriteLine("u2.Age=" + u2.Age); //输出:u2.Age=100,因为u1/u2指向同一个对象

按值传递

  • 对于引用类型(int a):传递的是变量a的值 拷贝的副本,因此原本的a值并没有改变。
  • 对于引用类型(User user):传递的是变量user的引用地址(User对象示例的内存地址)拷贝副本,因此他们操作的都是同一个User对象实例。
       private void DoTest(int a)
        {
            a *= 2;
        }

        private void DoUserTest(User user)
        {
            user.Age *= 2;
        }

        [NUnit.Framework.Test]
        public void DoParaTest()
        {
            int a = 10;
            DoTest(a);
            Console.WriteLine("a=" + a); //输出:a=10
            User user = new User();
            user.Age = 10;
            DoUserTest(user);
            Console.WriteLine("user.Age=" + user.Age); //输出:user.Age=20
        }

按引用传递

按引用传递的连个主要关键字:outref,不管是值类型还是引用类型,按引用传递的效果都是一样的,都是传递的是地址的引用(类型c++的指针)。outref告诉编辑器方法传递的是参数地址,而不时参数本身。

        private void DoTest( ref int a)
        {
            a *= 2;
        }

        private void DoUserTest(ref User user)
        {
            user.Age *= 2;
        }

        [NUnit.Framework.Test]
        public void DoParaTest()
        {
            int a = 10;
            DoTest(ref a);
            Console.WriteLine("a=" + a); //输出:a=20 ,a的值改变了
            User user = new User();
            user.Age = 10;
            DoUserTest(ref user);
            Console.WriteLine("user.Age=" + user.Age); //输出:user.Age=20
        }

out和ref的主要异同

  • out和ref都知识编译器传递的参数地址,在行为上都是相同的。
  • 他们的使用机制稍微有不同,ref要求参数在使用之前要显式初始化,out要在方法内部初始化。
  • out和ref不可以重载,就是不能定义Method(ref int a)和Method(out int a)这样的重载,从编译角度来看,二者的实质是相同的,只有使用时有区别。

    参考网址:https://www.cnblogs.com/anding/p/5229756.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值