gpt4 book ai didi

c# - 重用对象会导致 List 冗余

转载 作者:太空宇宙 更新时间:2023-11-03 17:54:15 24 4
gpt4 key购买 nike

我遇到了一个问题,我在 IQueryable 对象中获取返回的数据并且重复了。我通过将用于构建集合的临时对象从方法作用域移动到循环作用域来解决它。换句话说,每次循环重复时它都会被清除。

原文:

private void MyMethod()
{
SomeObj ProjDtl = new SomeObj(); //here is the obj method scoped


foreach (ReservedSimProjects item in parameters.ReservedProjects.ReservedSimProj)
{

IQueryable<SJ> DbProj = SimColl.Where(e => e.SimProjectID == item.ProjectId);

ProjDtl.ProjName = DbProj.First().ProjName;
ProjDtl.ProjArea = DbProj.First().ProjArea;
ProjDtl.ProjPerim = DbProj.First().ProjArea;
....etc....

ProjectsDetails.Add(ProjDtl);
}

现在我显然不正确的想法 ProjDtl 将被创建一次并被重用。随着循环迭代,旧值将被新值覆盖。这似乎正是正在发生的事情。通过调试器,ProjDtl 属性被覆盖,但最后一行将它添加到集合中,添加了第一遍的原始内容,因此我的集合有重复项、一式三份等。更改范围以便每次通过都重新创建对象已解决问题。为什么因为有某种指向原始对象的指针并且它没有更新,即使它的每个属性都被重新分配了???

private void MyMethod()
{

foreach (ReservedSimProjects item in parameters.ReservedProjects.ReservedSimProj)
{

SomeObj ProjDtl = new SomeObj(); //here is the obj method scoped

IQueryable<SJ> DbProj = SimColl.Where(e => e.SimProjectID == item.ProjectId);

ProjDtl.ProjName = DbProj.First().ProjName;
ProjDtl.ProjArea = DbProj.First().ProjArea;
ProjDtl.ProjPerim = DbProj.First().ProjArea;
....etc....

ProjectsDetails.Add(ProjDtl);
}

所以这一次我设法解决了自己的问题,但我不确定为什么/解决了什么问题。

JB

最佳答案

当您使用new 创建一个对象时,内存中会为它保留一些空间。用于访问对象的变量并不直接存储对象,而是指向对象位置的指针。

SomeObj ProjDtl = new SomeObj();

RAM:
+--------------------+-----------------------------+
| 0x12345 | 0xabcdef |
+--------------------+-----------------------------+
| ProjDtl = 0xabcdef | [data for a SomeObj object] |
+--------------------+-----------------------------+

在你原来的循环中,你有多个变量,但每个变量都指向内存中的相同地址并使用相同的实际对象:

SomeObj ProjDtl = new SomeObj(); //now ProjDtl points to 0xabcdef
foreach (ReservedSimProjects item in parameters.ReservedProjects.ReservedSimProj)
{
IQueryable<SJ> DbProj = SimColl.Where(e => e.SimProjectID == item.ProjectId);

ProjDtl.ProjName = DbProj.First().ProjName; //Since ProjDtl is never overwritten,
ProjDtl.ProjArea = DbProj.First().ProjArea; //it will always point to 0xabcdef,
ProjDtl.ProjPerim = DbProj.First().ProjArea; //and you're always accessing the same physical object's data
....etc....

ProjectsDetails.Add(ProjDtl);
}

在您更正后的版本中,每次在循环内创建新对象时,您都会在内存中为新对象预留更多空间并改为修改其详细信息。

private void MyMethod()
{

foreach (ReservedSimProjects item in parameters.ReservedProjects.ReservedSimProj)
{
SomeObj ProjDtl = new SomeObj(); //On the first iteration, ProjDtl might point to 0xabcdef,
//on the second, 0x98765, on the third, 0xfedcba... but it will always be a new, unused memory address

IQueryable<SJ> DbProj = SimColl.Where(e => e.SimProjectID == item.ProjectId);

ProjDtl.ProjName = DbProj.First().ProjName; //Now, each iteration modifies a different
ProjDtl.ProjArea = DbProj.First().ProjArea; //physical object
ProjDtl.ProjPerim = DbProj.First().ProjArea;
....etc....

ProjectsDetails.Add(ProjDtl);
}

关于c# - 重用对象会导致 List<T> 冗余,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15775074/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com