在C#中修改列表内的列表

时间:2017-05-10 12:56:00

标签: c#

我试图通过迭代列表来修改内部列表中的值。但是,无论外部列表如何,我都会在内部列表中获得相同的结果。我预计maxSpeed的结果对于不同的车辆是不同的。

希望有人可以为此提供帮助。

请注意,这不是随机数生成器问题。 这只是我生成的示例代码,这个问题确实存在于我的项目代码中而不使用随机数生成器。

Run C# code here

List<Vehicle> mainList = new List<Vehicle>();
List<Properties> defaultPropertyList = new List<Properties>{
    new Properties() { maxSpeed = 0, isTwoDoor = true },
    new Properties() { maxSpeed = 0, isTwoDoor = true },
};


mainList.Add(
    new Vehicle() {
        number = 1,
        property = new List<Properties>(defaultPropertyList)
    }
);
mainList.Add(
    new Vehicle() {
        number = 2,
        property = new List<Properties>(defaultPropertyList)
    }
);           

foreach(Vehicle vehicle in mainList) {
    Random rnd = new Random();
    vehicle.property.ForEach(x => x.maxSpeed =  rnd.Next(1, 100));
}

2 个答案:

答案 0 :(得分:5)

问题在于,当您为每辆车初始化property字段时,您将添加对相同的两个Properties对象(在顶部定义)的引用。所以它们存在于所有车辆中,当你修改它时,它会在两个地方被修改(因为它是相同的参考)。

初始化新车时,您需要在defaultPropertyList中复制对象。然后它们将独立存在。

一种方法:为Vehicle创建一个新的构造函数,它接受默认属性,然后将它们复制到那里。

public Vehicle(List<Properties> defaultProps) 
{
  property = new List<Properties>();
  foreach (var p in defaultProps)
  {
    var newProp = new Properties {
                                    maxSpeed = p.maxSpeed,
                                    isTwoDoor = p.isTwoDoor
                                    // add any other properties here
                                 };
    property.Add(newProp);
  }
}

答案 1 :(得分:1)

defaultPropertyList只是一个包含一组项目的列表。每个Vehicle都有List<Properties>的相同实例。每Vehicle个没有一个。只有一个,他们都在分享它。这就是为什么无论你如何改变属性,它们都具有相同的属性。

要修复它,请不要创建并共享它。只需创建您需要的任意数量。也许这不是你,但是当我开始时,我害怕创建大量的对象,并认为我可以通过尽可能少的创建来优化。

虽然我们不希望不必要地创建大量昂贵的对象,但没有必要对它嗤之以鼻。尽可能多地创建。例如,在Web应用程序中,甚至无法跟踪为响应单个请求而创建的对象数。

你可以这样做:

Random rnd = new Random(); // Despite what I just said,
                           // you only need one of these this time.
foreach(Vehicle vehicle in mainList) {        
    vehicle.property = new List<Properties>{
        new Properties() { maxSpeed = rnd.Next(1, 100), isTwoDoor = true },
        new Properties() { maxSpeed = rnd.Next(1, 100), isTwoDoor = true },
}