2017-02-09 35 views
1

我已经构建了下面的简单示例来说明我在我的实际代码中所遇到的问题,它比较复杂。列表中每个迭代覆盖列表中的对象属性

首先,我简单的类:

public class InnerTemp { 
    public int A { get; set; } 
    public int B { get; set; } 
    public int C { get; set; } 
} 

public class OuterTemp { 
    public List<InnerTemp> InnerTemps { get; set; } 
} 

和实现:

var outerTemps = new List<OuterTemp>(); 
var innerTemps = new List<InnerTemp>(); 
innerTemps.Add(new InnerTemp() { A = 1, B = 2, C = 3 }); 
innerTemps.Add(new InnerTemp() { A = 4, B = 5, C = 6 }); 

for(int i = 1; i < 5; i++) { 
     foreach(InnerTemp innerTemp in innerTemps) { 
      innerTemp.A += i; 
      innerTemp.B += i; 
      innerTemp.C += i; 
     } 

     var outerTemp = new OuterTemp() 
     { 
      InnerTemps = innerTemps 
     }; 

     outerTemps.Add(outerTemp); 
} 

我将在最后一行我的断点,右大括号。按照预期,在第一次迭代中,outerTemps[0].InnerTemps[0].A的值为2。但是在第二个循环中,outerTemps[0].InnerTemps[0].A的值变成了4,这让我感到困惑。第一个对象的属性A仅仅因为添加了另一个对象而被踩踏。我完全认为outerTemps[1].InnerTemps[0].A是不同的,但为什么我的原始财产跺脚?

如何更改此设置,以便每次将新对象添加到集合时都不会覆盖先前的对象属性?

+0

你想要什么'outerTemps [0] .InnerTemps [0] .A'在第二个循环? – IllidanS4

+2

你应该看看[浅vs深层复制](http://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow-copy) 。您正在复制对“innerTemps”的引用,而不是对所有元素进行深层复制。这会导致为每个outerTemp对象修改相同的InnertTemp引用。 –

+0

它很明显,你正在修改每个迭代中的相同列表。您需要创建一个InnerTemp的新列表,其中包含外部for循环的每次迭代中的所有对象的深层副本。 –

回答

2

正如我在我的评论中提到的,您正在创建innerTemps列表的浅表副本,该副本会导致复制引用而不是创建列表中每个InnerTemp对象的深度副本。

如果您希望在新创建的OuterTemp中单独使用InnerTemp对象,这些对象将分别进行跟踪和修改,您必须创建它们的深层副本。

每建议here我会建议您InnerTemp类创建一个Copy方法:

public class InnerTemp 
{ 
    public int A { get; set; } 
    public int B { get; set; } 
    public int C { get; set; } 

    public static InnerTemp Copy(InnerTemp source) 
    { 
     return new InnerTemp { A = source.A, B = source.B, C = source.C }; 
    } 
} 

,并使用创建的每个OuterTemp新的列表时:

var outerTemp = new OuterTemp() 
{ 
    InnerTemps = innerTemps.Select(InnerTemp.Copy).ToList(); 
}; 

这将防止outerTemps列表中的值被循环计数器修改。请注意,.ToList()通过评估Select enumerable并返回一个新列表隐式创建深层副本,因此您不必担心导致问题的列表引用。

+0

谢谢你的Moffat。 – HerrimanCoder

相关问题