如有引用类型Point,它有两个字段:int x, int y,那么
var p=new Point();
p.x=10;
p.y=20;
这样赋值会装箱吗?
我理解的是堆上所有类型都有类型对象指针和同步块索引,至少要有类型对象指针,否则CLR无法知道其真实类型(因为存在继承,CLR根据类型对象指针才能知道这是基类还是派生类),所以上面的代码也需要装箱。
但是看书上说泛型集合不需要装箱,因为泛型集合的接口参数是值类型,比如List<int>的Add方法,但我不明白,List是在堆里,List的每个元素也是在堆里,元素保存的只是一个int,没有类型对象指针吗?
第一个问题:因为new其实是在堆里分配了空间,实例化了一个类对象(x和y两个int值也分配好了空间,大小为4字节),所以这样赋值不会存在装箱拆箱。
2. 第二个问题:List<int>其实是一个容量可动态伸缩的数组,也是分配到堆里面的。所以也 不存在装箱和拆箱。int是值类型,不是类,不需要什么类型对象指针。整个List<int>是一 个类对象,它本身有对象指针而已。
问题中的操作不需要装箱。
你的理解模型有问题,抱歉我能力欠缺,暂时没办法文字描述出我的理解模型。
List本身是class,不在堆里。List的每个元素也不在堆里。
拆箱装箱,值类型,引用类型,这些和堆栈没有必然联系。
C#从来都是让程序员不要去管堆栈,本来就对上层不透明的,最近几年才填加了stackalloc等一些强制手动分配的关键字。
一本书<CLR via C#>建议看一下。我印象中即使是这本深入clr的书,也都很少提及堆栈。
网上的很多结构体优化也都是为了有更高的几率被分配到堆上。