您的位置:首页 > 编程语言 > C#

C#.NET底层 List 集合循环添加对象(如:list.add(model)),为什么会出现整个list集合都是一样的数据?

2018-03-09 18:06 756 查看
先考考大家,这段代码,有没有问题?
stuModel mod = new stuModel();
while (dr.Read())
{
mod.DDID = dr["DDID"].ToString();
mod.CPfenlei = dr["CPfenlei"].ToString();
mod.CPguige = dr["CPguige"].ToString();
mod.CPMach = (int)dr["CPMach"];
mod.CPName = dr["CPName"].ToString();
mod.CPyanse = dr["CPyanse"].ToString();
list.Add(mod);
}

发现了吗?这样写,把mod对象的实例化放在循环外面,最后的结果,就如我们题目中出现的,出来数据是一样的,并且就是最后一条数据。这是我们经常忽略的问题,因为出于性能考虑,我们一般把实例化对象写在循环外面,但是,便出现了这个问题,那么这是为什么呢?原因就是:代码中实例化mod对象时,内存中就把这一个mod对象存储在了堆上,并且在栈上分配了一个指向堆的地址;我们在一次次循环,改变mod的各个属性值的时候,其实是在改变堆,但是list.add(mod)的时候,添加mod对象,实际上是添加mod存在栈上指向堆的地址,地址自始至终没有发生改变,而堆上的数据,一直在被覆盖,直到最后一条数据;所以,到最后,我们分现,数据总数对,但是数据却是一样的,并且还都是最后一条的原因,就是这个!

我们只需要把实例化对象的操作,写在循环内部就好,这种情况下,不需要考虑对象的释放,在.NET底层机制下,垃圾回收机制已经成熟,例如这样的创建对象,在当次(i)循环结束时,就是立即释放,再进行下次(i+1)循环;
while (dr.Read())
{
stuModel mod = new stuModel();
mod.DDID = dr["DDID"].ToString();
mod.CPfenlei = dr["CPfenlei"].ToString();
mod.CPguige = dr["CPguige"].ToString();
mod.CPMach = (int)dr["CPMach"];
mod.CPName = dr["CPName"].ToString();
mod.CPyanse = dr["CPyanse"].ToString();
list.Add(mod);
}

那么,我们有时又会见到这样的代码:
stuModel mod = new stuModel();
while (dr.Read())
{
mod = Class1.MapEntity<stuModel>(dr, properties);//此方法的返回值就是stuModel
list.Add(mod);
}

在这个时候,为什么mod对象的实例化,写在循环外面,但是最后数据却是正常的呢?这是因为每次循环时,mod的地址发生了改变,因为MapEntity方法都把一个新的mod,赋值给了我们看到的mod,这里赋值的便是栈上的地址;

----欢迎加入博主个人的技术交流QQ群:121942786(BUG制作者协会)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐