最近码墙时发现了一个很有意思的问题,定义一个引用对象,如果在循环外面定义对象,在循环里list.add(对象),最后的结果却是所有的对象值都是一样的,即每add一次,都会把之前所有的数据覆盖掉,蛮有趣的,在网上轻松的搜到了答案,把对象在循环里new就行了,问题虽然解决了,但感觉这里面包含了一些.net底层存储的知识,有关于引用类型和值类型的存储方式问题,写了个demo总结了一下,水平,有大牛发现demo中有不足之处还请指正。

  如下面两图:

图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对象,会消耗大量的内存。

感觉这次小实验挖出了很多东西,要深入研究一下。

list add元素覆盖之前元素问题思考的更多相关文章

  1. 不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁

    不要在 foreach 循环里进行元素的 remove/add 操作.remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁. 正例: Iterator&l ...

  2. list,set等集合遍历时,不能remove集合中的元素。需要new一个Object或者list,set,里面add需要删除的元素,等集合遍历完了进行remove(Object)或者removeAll(list/set)操作

    list,set等集合遍历时,不能remove集合中的元素.需要new一个Object或者list,set,里面add需要删除的元素,等集合遍历完了进行remove(Object)或者removeAl ...

  3. CSS3 04. 伸缩布局、设置主轴,侧轴方向、主/侧轴对齐方式、 伸缩比例、元素换行、换行控制、覆盖父元素的align-items;控制子元素顺序、web字体、突变字体

    CSS3 在布局方面做了非常大的改进,对块级元素的布局排列变得十分灵活,适应性非常强,其强大的伸缩性,在响应式开发中可以发挥极大的作用.(兼容性不好) 必要元素: 指定一个盒子为伸缩盒子 displa ...

  4. DOM获取元素、修改元素

    ## DOM获取元素.修改元素### 1.DOM#### ①什么是DOM?作用? > DOM是文档对象模型 > 作用:操作网页内容,可以开发网页内容特效和实现用户交互.#### ②DOM对 ...

  5. HTML(二)HTML元素(整体结构,块级元素,内联元素,结构元素,交互元素,元素嵌套规则)

    HTML整体结构解释 <!DOCTYPE html> // 文件应以"<!DOCTYPE ......>"首行顶格开始,推荐使用"<!DOC ...

  6. WPF XMAL获取元素的父元素,子元素

    /// 获得指定元素的父元素 /// </summary> /// <typeparam name="T">指定页面元素</typeparam> ...

  7. HTML的display属性将行内元素、块状元素、行内块状元素互相转换以及三者的区别

    1.行内元素 查看演示 (1)设置宽高无效 (2)对margin仅设置左右方向有效,上下无效:padding设置上下左右都有效,即会撑大空间 (3)不会自动进行换行 <html> < ...

  8. 一个 VUE 组件:实现子元素 scroll 父元素容器不跟随滚动(兼容PC、移动端)

    介绍 我们经常遇到一种情况.当滑动滚动条区域时,子元素滚动条到底部或顶部时就会触发父级滚动条,父级滚动条同理会继续向上触发,直至body容器.这是浏览器默认的滚动行为. 但是很多情况,我们想要子元素滚 ...

  9. java:Conllection中的List,ArrayList添加元素,删除元素,输出元素

    java:Conllection中的List,ArrayList添加元素,删除元素,输出元素 //为list接口实例化 List<String> addlist = new ArrayLi ...

随机推荐

  1. Android 图片从网页中获取并动态加载到listview中

    实现功能: 效果图: 代码:这里

  2. 结构体dict_table_t

    typedef struct dict_table_struct dict_table_t; /** Data structure for a database table. Most fields ...

  3. BZOJ2351: [BeiJing2011]Matrix

    2351: [BeiJing2011]Matrix Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 589  Solved: 171[Submit][S ...

  4. GAC的理解及其作用

    转:http://www.cnblogs.com/smallstone/archive/2010/06/29/1767508.html 一.GAC的作用 全称是Global Assembly Cach ...

  5. ASP.NET MVC3细嚼慢咽---(2)模板页

    这一节演示下MVC3中怎样使用模板页,在传统的webform设计模式中,我们使用masterpage作为模板页,在MVC3 razor视图设计中,我们使用另一种方式作为模板页. 新建一个MVC3项目, ...

  6. 彻底解决:请求被中止: 未能创建 SSL/TLS 安全通道

    最近有个项目要调用客户用java写的带https的webservice,对方提供了证书文件 test.pfx,我这里调用方式如下: //webservice代理类 SvcService svc = n ...

  7. ARM-Linux配置DHCP自动获取IP地址

    备注:内核版本:2.6.30.9busybox版本:1.15.2 PC Linux和开发板Linux的工作用户:root 1. 配置内核:[*] Networking support --->N ...

  8. HDU-4515 小Q系列故事——世界上最遥远的距离

    小Q系列故事——世界上最遥远的距离 Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) ...

  9. 在iOS的XCode工程配置中为什么要用-all_load&-ObjC

    -ObjC 这个flag告诉链接器把库中定义的Objective-C类和Category都加载进来.这样编译之后的app会变大(因为加载了其他的objc代码进来).但是如果静态库中有类和categor ...

  10. BestCoder Round #81 (div.2)C String

    总体思路好想,就是在找K个不同字母的时候,卡时间. 看了大神代码,发现goto的!!!!998ms #include<cstdio> #include<cstring> #in ...