搞清楚C#中的值类型(基础类型)和引用类型
作者:互联网
关于引用类型的值改变
参考: https://blog.csdn.net/nckyYang/article/details/76165741 值类型理解:变量的交换等于在一个新的地方按照连锁店的规范标准(统一店面理解为相同的变量内容)新开一个分店,这样新开的店与其它旧店互不相关、各自运营。 引用类型理解:变量的交换等于把现有一间店的钥匙(变量引用地址)复制一把给了另外一个老板,此时两个老板同时管理一间店,两个老板的行为都有可能对一间店的运营造成影响。 简单来说:值类型的值发生改变后,不会影响改变之前的值。举个例子: function chainStore() { var store1='Nike China'; var store2=store1; store1='Nike U.S.A.';//在这里store1的值改变了,但下面输出的时候仍然是没改变之前的值. alert(store2); //Nike China } chainStore(); //把一个值类型(也可以叫基本类型)store2传递给另一个变量(赋值)时,其实是分配了一块新的内存空间,因此改变store1的值对store2没有任何影响,因为它不像引用类型,变量的交换其实是交换了指像同一个内容的地址。 而引用类型的值发生改变后,只是改变前的变量名和改变后的变量名(即使前后变量名没有发生改变)在堆中的引用地址不一样了,而这两个地址指向的是栈中的同一个数据。所以说引用类型变量修改后,其指栈中的数据也改变了。 function chainStore() { var store1=['Nike China']; var store2=store1; alert(store2[0]); //Nike China store1[0]='Nike U.S.A.'; alert(store2[0]); //Nike U.S.A. } chainStore(); //在上面的代码中,store2只进行了一次赋值,理论上它的值已定,但后面通过改写store1的值,发现store2的值也发生了改变,这正是引用类型的特征,也是我们要注意的地方。 -------------------------------------------------- 引用类型与值类型相同的是,结构体也可以实现接口;引用类型可以派生出新的类型,而值类型不能;引用类型可以包含null值,值类型不能;引用类型变量的赋值只复制对象的引用,而不复制对象本身。而将一个值类型变量赋给另一个值类型变量时,将复制包含的值。 值类型及基本数据类型,常被分为四类八种: 四类:整型,浮点型,字符型,逻辑型 八种:1,整型3种 byte, short, int, long 2,浮点型 float, double 3,字符型 char 4,逻辑型 boolean引用类型
除了四类八种的基本类型,其他数据类型都是引用类型,例如:string类型,object类型等。传递:
值传递:基本数据类型复制都属于值传递。传递的是实实在在的变量值,是原参数的拷贝,实参传递给形参的值,形参发生变化而不影响实参。 引用传递:引用类型之间的赋值属于引用传递。传递的对象是引用的地址,即将实参的地址传递给形参,形参改变了实参也相应发生变化,因为指向同一个地址。 存储: 引用类型在栈中存储一个引用,其实际的存储位置位于托管堆。为了方便,简称引用类型部署在托管堆上。值类型总是分配在它声明的地方,作为字段时,跟随其所属的变量(实例)存储;作为局部变量时,存储在栈上。 1. 值类型:只需一段单独的内存,用于存储时间的数据。 引用类型:需要两端内存: 第一段:实际数据,总是位于堆中 第二段:一个引用,指向数据在堆中的存储位置 数据如果不是其他类型的成员就会像下图一样存贮,对于值类型数据放在栈中。对于引用类型数据放在堆中而引用放在栈中 2.存储引用类型对象的成员 引用类型对象的数据始终存储在堆中,如下图。 值类型数据,或引用类型数据的引用可以放在堆里,也可以放在栈里。 例如:引用类型的对象名称为MyType,有两个成员:一个值类型成员和一个引用类型成员,将如何存储呢? 对于一个引用类型,其实例的数据始终放在堆里。既然两个成员都是对象数据的一部分,那么他们都会被放在堆里,无论是值类型还是引用类型 如图: 装箱和拆箱 装箱就是值类型转化为引用类型的过程。将一个值类型变量装箱成一个引用类型变量,首先会在托管堆上为新的引用类型变量分配内存空间,然后将值类型变量拷贝到托管堆上新分配的对象内存中,然后返回新分配的对象内存地址。 例如: int val = 100; object obj = val; Console.WriteLine (“对象的值 = {0}",obj); 拆箱操作即是装箱的逆操作,拆箱的过程,是将值类型转换为引用类型,再由引用类型转换为值类型的过程。 为什么要装箱和拆箱? 装箱和拆箱的过程中涉及堆和栈的转换。直接影响性能,使用装拆箱是C#面向对象的精髓。处理大型的程序和软件,特别是有大批量数据的时候,这个很有必要的,比如代码片段中: 如果不使用装箱,就必须使用string[]strList=new string[5000000],这样就造成严重的性能问题。 (6)辨明值类型和引用类型的使用场合。 在C#中,我们用struct/class来声明一个类型为值类型/引用类型。考虑下面的例子: 如果SomeType是值类型,则只需要一次分配,大小为SomeType的100倍。而如果SomeType是引用类型,刚开始需要100次分配,分配后数组的各元素值为null,然后再初始化100个元素,结果总共需要进行101次分配。这将消耗更多的时间,造成更多的内存碎片。 所以,如果类型的职责主要是存储数据,值类型比较合适。一般来说,值类型(不支持多态)适合存储供C#应用程序操作的数据,而引用类型(支持多态)应该用于定义应用程序的行为。通常我们创建的引用类型总是多于值类型。如果满足下面情况,那么我们就应该创建为值类型: 该类型的主要职责用于数据存储。 该类型的共有接口完全由一些数据成员存取属性定义。 该类型永远不可能有子类。 该类型不具有多态行为。标签:存储,搞清楚,变量,store1,C#,引用,类型,store2 来源: https://www.cnblogs.com/gaoyangdev/p/13061096.html