Unity基础系列:C#的值类型和引用类型

Unity基础系列:C#的值类型和引用类型

大家好呀!我是稿费,想了很久准备回归写一写博客,希望自己的理解能帮助到有需要的人(当然有些理解可能是有偏差的,毕竟还是菜鸟一个嘛,希望大家能狠狠指出来鞭策我!!!)

如果需要转载使用则需要附上作者跟原文链接!毕竟打字超累的好不好!

C#的值类型和引用类型的区别

首先抛开什么堆跟栈一大堆的东西,值类型(例如int,float之类的基础类型都属于值类型(string是引用类型,但是每次赋值新变量都是拷贝,行为像值类型),自定义的值类型就enum和struct)和引用类型的区别就是:值类型的使用是拷贝,引用类型的使用是引用。(好像没说一样)

俗话说得好,实践出真章,让我们直接看下代码理解下上面那句话

public class Test : MonoBehaviour
{
    
    public struct MyStruct {
        public int structInt;
    }
    
    public class MyClass {
        public int classInt;
    }
    
    // Start is called before the first frame update
    void Start() {
        // Struct
        MyStruct myStruct1 = new MyStruct();
        myStruct1.structInt = 1;
        MyStruct myStruct2 = myStruct1;
        myStruct2.structInt = 2;
        Debug.Log($"Stuct1 value is : {myStruct1.structInt}");
        Debug.Log($"Stuct2 value is : {myStruct2.structInt}");
        
		// Class
        MyClass myClass1 = new MyClass();
        myClass1.classInt = 1;
        MyClass myClass2 = myClass1;
        myClass2.classInt = 2;
        Debug.Log($"Class1 value is : {myClass1.classInt}");
        Debug.Log($"Class2 value is : {myClass2.classInt}");
    }
}

上面就是我们的测试代码啦!我们先不看结果大家可以猜猜答案是什么!
1.
2.
3.
公布答案:
在这里插入图片描述
很神奇是嘛!Class1的改变居然影响了Class2!

现在让我们通过我们上面所说的来理解下为什么会产生这样的结果:

首先是Struct

  1. struct1通过copy将自己本身复制一份一模一样的给了struct2(相当于struct1告诉struct2:卷子我复印一份给你吧!)
  2. struct2拿到copy后,相当于一份独立的副本(struct2说:行吧!那我就拿走了)
  3. struct1的修改已经独立于struct2,互不影响。(struct1拿回家后发现有需要修改的地方进行修改,但是struct2手上的卷子却还是之前的版本)

值类型的拷贝就可以用上面的例子来理解

接下来我们看下Class到底做了什么吧

  1. class1则是将自己持有的class1的引用交给了class2。(类比上面的struct1和struct2,只是这次class1将装卷子的文件袋跟class2共享了,而不是复印一份)
  2. class1和class2操作的变量其实是同一个东西(因为从始至终卷子都没被拷贝,就算class1修改了卷子,class2打开书包看到的也是同一个修改后的卷子)

相信通过上面的例子大家已经理解了吧~

现在让我们想想他们分配的地方:堆和栈

  1. 对于引用类型想都不用想,一定分配在托管堆内!(没错就是这么霸道)
  2. 对于值类型则是看情况,如果在函数体内用完就丢弃(不出现闭包的情况)则在栈上分配。如果是在class内部声明的值类型,那么sorry啊,就是跟随class在堆上分配。
  3. 这个是重点,那天被问到了一个问题,我整个人都愣住了:如果值类型内部含有一个引用类型,那他是如何分配内存,会在栈上还是堆上!其实弄清楚这个概念很重要的一点是无论是引用类型还是值类型,他们得字段其实存的都是一个变量的内存位置。所以就算值类型里面含有引用类型,其实可以当做特殊的int处理。只是值类型内部class指向的东西是在堆里面。通过上面的分析大家也可以知道,就算值类型内部含有引用字段也是当做普通的值类型处理。(不好理解吧,直接上代码!!!!)
public class Test : MonoBehaviour
{
    public struct MyStruct {
        
        public int structInt;

        public MyClass structClass;
    }
    
    public class MyClass {
        public int classInt;
    }
    
    // Start is called before the first frame update
    void Start() {
        // Struct
        MyStruct myStruct1 = new MyStruct();
        myStruct1.structInt = 1;
        myStruct1.structClass = new MyClass();
        myStruct1.structClass.classInt = 1;
        MyStruct myStruct2 = myStruct1;
        myStruct2.structInt = 2;
        myStruct1.structClass.classInt = 2;
        Debug.Log($"Stuct1 value is : {myStruct1.structInt}");
        Debug.Log($"Stuct2 value is : {myStruct2.structInt}");
        Debug.Log($"Stuct1Class value is : {myStruct1.structClass.classInt}");
        Debug.Log($"Stuct2Class value is : {myStruct2.structClass.classInt}");
    }
}

输出:
在这里插入图片描述
这些就是全部啦,相信通过这个文章一定让你对值类型和引用类型有更多的理解吧!

参考链接
什么是C#的值类型与引用类型?Class与Struct对比

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值