遇到一个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. 《Python基础教程》第六章:抽象(一)

    用def定义函数 __doc__是函数属性.属性名中的双下划线表示它是个特殊属性

  2. 10-SQLServer中统计信息的使用

    一.总结 1.网址https://docs.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-stats-tr ...

  3. 初识 MQTT——IBM

    为什么 MQTT 是最适合物联网的网络协议  官方网址: http://mqtt.org/ Michael Yuan2017 年 6 月 14 日发布 WeiboGoogle+用电子邮件发送本页面 0 ...

  4. BZOJ 1984: 月下“毛景树” (树链剖分+线段树)

    注意赋值和加法的标记下传优先级.具体看代码. CODE #include <vector> #include <queue> #include <cstdio> # ...

  5. vue 手机物理返回键关闭弹框

    1.打开弹窗调用 window.history.pishState() 函数 2.关闭弹框 3.mounted 生命周期 监听popstate 事件 4.beforeDestroy 生命周期 移除po ...

  6. hdu 5733 tetrahedron 四面体内切球球心公式

    tetrahedron Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  7. firefox 丢失的回话

    升级了新版Firefox后如果插件被禁用的,可以在Firefox配置编辑页面(about:config页面)把 xpinstall.signatures.required首选项设为false来强制禁用 ...

  8. Codeforces 385C Bear and Prime Numbers(素数预处理)

    Codeforces 385C Bear and Prime Numbers 其实不是多值得记录的一道题,通过快速打素数表,再做前缀和的预处理,使查询的复杂度变为O(1). 但是,我在统计数组中元素出 ...

  9. HDU 5894 hannnnah_j’s Biological Test ——(组合数)

    思路来自于:http://blog.csdn.net/lzedo/article/details/52585170. 不过并不需要卢卡斯定理,直接组合数就可以了. 代码如下: #include < ...

  10. How to correctly set application badge value in iOS 8?

    o modify the badge under ios8 you have to ask for permissions let settings = UIUserNotificationSetti ...