c#List中add方法存在的问题
如下面两图:
图1:在外面定义对象a,调试界面中可以看到,i=4时,之前list中所有对象都被覆盖了
图2:在循环里定义对象a,不会被覆盖
又用值类型(int,short之类的)试了一下,在循环外面不会被覆盖,结果就不截图了,实验了以后,用一个大牛总结的一句话来说就是:对于List<T>来说,如果T是引用类型,那保存的是引用,如果是值类型,保存的是值本身!
但是上面的总结中有个特列:string类型。string在.net中很特殊,.net官方把它归到了引用类型中,但它却和值类型特别相似,具体讲解参考园友停留的风的这篇文章:http://www.cnblogs.com/yank/archive/2011/10/24/2204145.html。
用string实验结果如下:
显而易见,string不会覆盖之前的数据,是引用类型中的特列。
深入的思考了一下覆盖的原因(水平有限,欢迎大家补充),应当如下:
1.对于引用类型,在循环外new了 a 对象后,这个对象的引用地址就确定了,执行到第二次list.add()时,list[0]中保存的a对象和新加的list[1] a对象是同一个对象,使用的是同一个地址,也就是说在添加list[1]是,list[0]也被修改了,因为它俩指针指向同一个地址,同样,后面添加的都会修改前面所有对象,结果就是list最后所有数据都是最后的list[end_num]。
2.string也是引用对象,有唯一的引用地址(假设分配的是address1),但当add list[1]的时候(str值改变时),.net会检查内存,发现不等于之前的字符串(list[1]不等于list[0]),.net会给原来的str重新分配内存空间address2,存储list[0],而list[1]使用原来的空间address1。这样使得每次list.add时都不会覆盖之前的元素,因为它们使用的是不同的地址空间。
这也解释了我之前socket项目中接收数据是用StringBuilder,而不是string,每次改变string时,会消耗一份内存,socket接收中频繁的处理string对象,会消耗大量的内存。