1

我遇到了一个问题,我在 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

4

5 回答 5

4

使用 创建对象时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);
  }
于 2013-04-02T21:59:49.137 回答
3

为什么因为有某种指向原始对象的指针,即使它的每个属性都被重新分配,它也没有更新???

这是正确的。

您已经创建了一个对象。您可以根据需要多次设置该对象的所有属性,但它仍然是同一个对象。

每次调用 时ProjectDetails.Add(ProjDtl),都会将相同的对象添加到列表中。

该列表不存储对象属性的值 - 它存储对对象本身的单个引用。

您的固定示例有效,因为您每次都在循环周围创建一个新对象。然后设置该特定对象的属性并将其添加到列表中。

这意味着列表最终包含对许多不同对象的引用,每个对象都有自己的属性值。

于 2013-04-02T21:53:34.697 回答
1

是的,那个“指向原始对象的指针”实际上是你的变量。 在每次迭代时将该对象的引用ProjectsDetails.Add添加到您的列表中。但由于它是同一个变量,所以它是同一个对象!因此,您所做的就是在循环中一遍又一遍地覆盖该实例的属性。如果您的列表有 N 个值,那么您将拥有一个包含 N 个项目的列表,它们都指向同一个实例。

于 2013-04-02T21:53:06.287 回答
1

您不能像那样重用您的对象,因为它会尝试多次保存同一个对象。

您可以重用变量,但不能重用对象

private void MyMethod()
{
  SomeObj ProjDtl = null;


  foreach (ReservedSimProjects item in parameters.ReservedProjects.ReservedSimProj)
  {
     ProjDtl = new SomeObj()
     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);
  }
于 2013-04-02T21:54:15.883 回答
0

为什么因为有某种指向原始对象的指针,即使它的每个属性都被重新分配,它也没有更新???

是的 - 非原始和非结构类型是“引用类型” - 这意味着当您创建该类型的变量时,您正在创建指向该实例的引用(指针),因此在循环中重新分配值确实会影响同一个实例每一次。

您的解决方案是正确的。

于 2013-04-02T21:54:15.467 回答