遇到一个bug,抓耳挠塞好久都没有解决,有必要记录一下。

现在我使用了一个多维list。

IList<IList<int>> list = new List<IList<int>>();

我在main函数中调用了方法函数,在方法函数中使用list.add()方法向list中添加sublist。添加代码如下:

IList<int> l = new List<int>();
for(int i=;i<;i++)
{
if (条件)
{
l.clear();
list.Add(sublist);
}
}

一共添加了3个元素

但是最终的list中,却始终只有第三个sublist,前两个sublist存在,但是为空。这就非常奇怪,既然前两个元素存在,那么就代表list.Add(sublist)语句成功运行了,但为什么值为空呢?

我第一时间就怀疑Add方法会覆盖掉之前的值,于是我又在main函数中手动添加了两个sublist,打印出来发现,后面添加的都能成功写入,只有循环内的不可以。

这段代码是在vscode里面写的,由于不能单步调试查看局部变量,耽搁了好多时间。于是我把所有代码移到了VS2017上,开始我的单步调试(VS2017大法好!)

我一步一步调试,发现第一个sublist写入是成功的,到了第二个sublist要写入的那一刻,刷!list[0]的值变成了空!

现在问题找到了,但是我不明白问题出在哪里。

在网上终于搜到了解决方法。原来是在循环中如果使用同一个sublist,那么每次add都会把之前覆盖掉。解决办法就是不要在循环外定义sublist,而是在循环内部定义。

该方法给出的解释如下:

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时都不会覆盖之前的元素,因为它们使用的是不同的地址空间。
————————————————
版权声明:本文为CSDN博主「IT登山家」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_35409640/article/details/71404203

但是呢,我在进一步调试中发现两个问题:

1.如果去除l.clear(),程序是正常的,list值全部正常,只有添加了l.clear(),list的前几个值才会被抹去。

2.在main函数中加这样的循环(包含l.Clear()),list可以正常写入

结合该方法,我认为覆盖的原因如下:

现在申请的所有类型在.net中都被认为是引用对象,当add的时候,.net会统一重新分配内存。但是在add之前,l都指向了l的地址,查了资料就知道,clear并不清除list内存,想必是只擦除了地址,所以才会既没有报错,也没有值。

至于在main函数中为什么不会发生这种现象,我还没有比较好的思路,可能是因为list是在main中一定,不需要引用函数,也就没有list的引用过程,可能add方法就直接写入list了。水平有限,欢迎有识之士补充。

C# List方法中存储的问题的更多相关文章

  1. List中存储同一个对象(内容不同)

    List中存储同一个对象,前面的会被后存入的对象覆盖,解决方法:每次存入新的对象

  2. 数据库中存储日期的字段类型究竟应该用varchar还是datetime ?

    背景: 前段时间在百度经验看到一篇文章<如何在电脑右下角显示你(爱人)的名字>,之前也听过这个小技巧,但没真正动手设置过.所以出于好奇就实践了一下. 设置完成后的效果例如以下.右下角的时间 ...

  3. c语言中float、double、long double在内存中存储方式

    存储格式中的二机制转为浮点数: 浮点型变量在计算机内存中占用4个字节(4 Byte),即32-bit,一个浮点数由2部分组成:底数m  和 指数e: 底数部分:使用2进制数来表示此浮点数的实际值: 指 ...

  4. 在配置文件(.settings、.config)中存储自定义对象

    原文:在配置文件(.settings..config)中存储自定义对象 引言 我前面曾写过一篇<使用配置文件(.settings..config)存储应用程序配置>,我在其中指出“sett ...

  5. JAVA 在程序中存储和修改信息

    1.语句和表达式 计算机程序是一组告诉计算机什么的指令,每一个指令称为语句. 2.指定变量类型 变量名.变量存储的信息类型 整型int(-2.14*109~2.14*109).浮点型float(38位 ...

  6. 求int型正整数在内存中存储时1的个数

    题目描述: 输入一个int型的正整数,计算出该int型数据在内存中存储时1的个数. 输入描述: 输入一个整数(int类型) 输出描述: 这个数转换成2进制后,输出1的个数 输入例子: 5 输出例子: ...

  7. java中的各种数据类型在内存中存储的方式

    原文地址:http://blog.csdn.net/aaa1117a8w5s6d/article/details/8251456 1.Java是如何管理内存的 java的内存管理就是对象的分配和释放问 ...

  8. 华为oj之求int型正整数在内存中存储时1的个数

    题目: 求int型正整数在内存中存储时1的个数 热度指数:4427 时间限制:1秒 空间限制:32768K 题目描述 输入一个int型的正整数,计算出该int型数据在内存中存储时1的个数. 输入描述: ...

  9. 数据库中存储日期的字段类型到底应该用varchar还是datetime

    将数据库中存储时间的数据类型改为varchar(),这时最好让这些时间是数据库中自动生成的(一个没有格式的输入也可能会导致输出错误),因为存储类型为varchar(),所以获取到的值也就被认为是一个字 ...

随机推荐

  1. DNS如何工作

    上一篇文章(什么是DNS)中,我们解释了 DNS 所涉及到的一些术语,接下来我们来看看 DNS 这个系统是如何工作的? 从高层次上看,这个系统非常简单,但是当你关注细节时,它又非常复杂.总的来说,它是 ...

  2. 关于Http协议,一片就够了

    转载:http://www.jianshu.com/p/80e25cb1d81a HTTP简介 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从 ...

  3. swoole_process模拟耗时操作

    一例串行阻塞操作 <?php $start = time(); $tasklists = [ '/root/文档/longtale1.txt', '/root/文档/longtale2.txt' ...

  4. php类知识----特别用法

    spl_autoload_register注册 <?php #spl_autoload_register-----这个例子是用来打印实例化类的类名 function thereisagameof ...

  5. css3 扇形动画

    扇形动画,因为我工作中遇到了只执行一次就ok,所以没细研究,该css暂时只能执行1次扇形动画,无限循环会有问题. css: @keyframes rotateAn{ 0%{transform: rot ...

  6. DOM 事件流与事件处理程序

    ㈠事件流 ▶事件:是文档和浏览器窗口中发生的,特定的交互瞬间. ▶事件流:描述的是从页面中接受事件的顺序   ⑴DOM事件冒泡 定义:事件最开始由最具体的元素(文档中嵌套层次最深的那个节点)接受,然后 ...

  7. vueCli和脚手架

    vue CLI相当于一个基于vue开发的框架:可以用来快速开发vue项目:   1.安装 由于需要用到npm命令,所以要先安装node.js:     node.js下载地址:https://node ...

  8. http 异步 接收 回传 数据文字和文件流

    public void HttpListenerStar() { try { HttpListener httpListener = new HttpListener(); httpListener. ...

  9. MySQL的密码操作命令

    一.请问在win2K命令提示符下怎样更改mysql的root管理员密码? >mysql -u root -p Enter password: ****** mysql> use mysql ...

  10. 未AC

    Count the Trees Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...