c#中推荐使用list而不用arraylist是为了避免拆箱装箱,但是我有个疑问,比如List<animal>这种父类的集合,存进了很多cat,dog这种类型的子类对象,这样效率是不是也不高呢,还是分别放在List<cat>和List<dog>中????
c#中推荐使用list而不用arraylist是为了避免拆箱装箱,但是我有个疑问,比如List<animal>这种父类的集合,存进了很多cat,dog这种类型的子类对象,这样效率是不是也不高呢,还是分别放在List<cat>和List<dog>中????
15 回答8.4k 阅读
8 回答6.2k 阅读
3 回答2k 阅读✓ 已解决
2 回答3.9k 阅读✓ 已解决
2 回答3.2k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
1 回答4k 阅读✓ 已解决
楼上两位都不懂C#。
C#在存class对象的时候也是指针,如果是ArrayList这种非泛型,或者List<Object>这种指定Object的泛型,存进去的struct/primitive(合称value type)数据,也是boxing之后得到一个地址然后存这个地址到集合里面;
Java没区别是因为类型擦除,C#里面List<class type>是没有这个boxing/unboxing的事情的。
cat、dog如果能派生自animal,就说明那不是struct。class对象在内存layout里面是包含了一个sync block和一个RTTI(就是具体类型的描述符),见此处。根据这个RTTI就可以判断具体类型,这个跟boxing/unboxing没半毛钱关系。class对象是不需要boxing和unboxing的。
value type之所以必须boxing/unboxing,是因为他的语义是:a.作为一个整体直接layout到当前位置,比如一个struct局部变量就是直接躺在栈上的,如果是class里面的一个field则直接躺到这个class对象所占的内存,而不是另外从别的地方分一片内存然后用个指针指向它(这种是class);以及b. 因此每次赋值都必须拷贝,而不是用个指针一指了事。正因为他是直接躺的,对于ArrayList这种无泛型的系统,如果允许各种不同大小的struct躺在ArrayList里面,那么元素大小就不等长,arrayList[i]就不能通过offset + i * elemSize计算获得,只能挨个元素遍历。这就变成了查找第N个元素的时间复杂度为O(N)的LinkedList,而不是O(1)的ArrayList了,显然是不符合你的预期的,并且实现代码会变得很艰难也很奇怪。
这种东西其实你不需要问,网上很多现成的答案,当然你得翻墙。自己google:dotnet memory layout,甚至最好自己看ECMA Spec,然后用Windbg然后!loadby sos clr自己看。
已经帮你贴了这么多链接了,继续伸手党就得剁手了。