. net中值类型和引用类型的区别

Boxing、GC、NET、Reference、StringBuilder、Type、Unboxing、Value这几个词在这个问题中都会出现。我们先来讲讲.NET中值类型和引用类型的区别。值类型主要是struct和一些基本数据类型,它们在内存里是直接存数据的,一般都在栈上。而引用类型像class、string还有数组,数据是在托管堆里,变量里存的是对象的地址。赋值的时候,值类型会把数据拷贝一份出来,大家互不影响;引用类型其实就是给对象地址做个复制,多个变量可能指着同一个东西。 说到性能这块,小型的值类型最好别去堆上占地方,能避开GC的压力。可如果值类型本身太大或者复制得太频繁,反而会多花时间去拷贝。对于复杂的对象和需要共享的数据,引用类型就更合适。合理选择类型就能把GC压力降下来,性能也会更好。 struct到底是在栈上还是堆上?其实不绝对。如果是在引用类型里当字段用,它就跟主人一起被分配在堆上;要是被装箱(Boxing)了,也是给放到堆里去。所以说值类型在栈上只是常见情况,关键还得看它放在哪儿。 那什么叫装箱(Boxing)和拆箱(Unboxing)呢?装箱就是把值类型转成object或者接口类型,这个过程会把数据给复制到堆上去;拆箱就是反过来把object变回原来的值类型。装箱会多产生堆分配和额外拷贝,容易造成GC压力,所以在高频调用或者处理集合的时候最好别搞隐式装箱。 为啥不建议把struct设计得太大?因为在赋值或者传参的时候它会被整体复制一遍。如果结构体里东西太多或者有数组这类的,复制起来成本可就高了,影响性能。所以通常建议结构体保持简单小巧,还最好做成不可变的这样能少出错也能提升速度。 string是值类型还是引用类型?其实它是引用类型。不过它有个特点叫不可变,每次改字符串都会新建个对象出来,所以表现得像值类型一样安全。正是因为这个不可变性才保证了多线程下的安全性,但是频繁拼接字符串会产生好多临时对象用StringBuilder优化一下就好。