4

我有一个对象(我创建的类)的列表(在 C# 中)。我可以使用该列表,但问题是我只创建了(实例化我认为是正确的术语)我的一个对象类,并且我一直将它添加到列表中,即使该对象的属性随着代码的迭代而改变. 我希望能够将硬编码对象添加到我的列表中,而不是引用对象。

这是我目前正在做的事情:

public class SaveData
{
    public double save_property1;
    public double save_property2;    
}

in the application

SaveData newSaveData = new SaveData();
List<SaveData> newSaveDataList = new List<SaveData>;

if ( some condition)
{
    newSaveData.save_property1 = x
}

if (some condition 2) 
{
    newSaveData.save_property2 = y 
    newSaveDataList.Add(SaveData);  // 
}

由于 X 和 Y 在迭代中发生变化,我希望SaveDate我添加到列表中的对象不会随着每次迭代而改变(因此我可以保留 Data 对象的历史记录),即硬编码而不用作参考。

4

4 回答 4

6

你不能这样做,每次你想添加到列表时都需要创建一个新对象,否则你将继续修改旧对象。

请记住,当您向列表添加引用类型时,您只是将其reference放入列表中,而不是被引用的对象。这意味着如果你总是推送同一个实例,列表中的所有“项目”实际上都是同一个项目。考虑:

newSaveData                        1000
+-----------+                      +--------------------+
| 1000      |--------------------->| save_property1     |
+-----------+                      | save_property2     | 
                                   +--------------------+
newSaveDataList                               ^
+-----------+                                 |
| 1000      |---------------------------------+
+-----------+                                 |
| 1000      |---------------------------------+
+-----------+                                 |
| 1000      |---------------------------------+
+-----------+                                 |
| 1000      |---------------------------------+
+-----------+

因此,您需要为每个添加到列表中的对象创建一个新的对象实例,以便它们都是可以变化的不同对象:

while (yourLoopCondition)
{
    // each item you want to add, create a new instance.
    newSaveData = new SaveData();
    if (someCondition1)
    {
        newSaveData.save_property1 = x
    }

    if (someCondition2) 
    {
        newSaveData.save_property2 = y 
        newSaveDataList.Add(newSaveData);  
    }
}

以上假设每个对象都是不同的,而不是循环的多次迭代中的“飞行中的对象”。

现在,如果您有一个主要对象并且您只是想将该对象的“快照”放入列表中,您可以使用某种克隆方法或“复制构造函数”来做到这一点:

public class SaveData
{
    public double save_property1;
    public double save_property2;

    public SaveData(SaveData other)
    {
        save_property1 = other.save_proerty1;
        save_property2 = other.save_property2;
    }
}

然后,如果您想将 asnapshot放在飞行中的对象列表中,您可以这样做:

newSaveDataList.Add(new SaveData(newSaveData));

或者,您可以使用 astruct代替,它是一种值类型,因此会在列表中放置一个副本,但struct有很多有趣的怪癖,在使用它们之前应该非常仔细地考虑这些怪癖。我在这里有一个关于这个主题的帖子

于 2012-10-26T13:46:17.477 回答
2

我想我明白你在问什么。您会发现自己拥有一个对同一对象的引用列表,该对象反映了最新状态(x和的值y),而不是一组对历史值的引用。

这样做的原因是您正在向列表中添加对同一对象的引用,并且您正在更改这个引用的对象,而不是每次都创建新对象。您应该能够SaveData在每次迭代中创建一个新的来解决您的问题。

var history = new List<SaveData>();
while (someCondition)
{
    var sd = new SaveData(...);

    if (someOtherCondition)
    {
        sd.saveProperty1 = someValue;
    }

    ...

    history.Add(sd);
}
于 2012-10-26T13:46:59.620 回答
0

我认为您的示例代码不太正确,因为您有

SaveData.save_property1 = x;

我认为你的意思

newSaveData.save_property1 = x;

试试这个,它展示了如何创建多个具有不同字段值的 SaveData 对象,并将对象添加到您的列表中。

List<SaveData> newSaveDataList = new List<SaveData>();
for (int index = 0; index < 10; index++)
{
    SaveData saveData = new SaveData();
    saveData.save_property1 = (double)index;
    saveData.save_property2 = (double)index * 2;
    newSaveDataList.Add(saveData);
}

foreach (SaveData saveData in newSaveDataList)
{
    Console.WriteLine(saveData.save_property1);
    Console.WriteLine(saveData.save_property2);
}
于 2012-10-26T13:54:33.500 回答
0

为了使事情起作用,您需要创建一个新对象并将先前对象中的所有字段复制到新对象中,然后更改所需的属性。复制操作是你需要自己实现的。此操作称为“克隆”。

看看这两个问题:

在 C# 中克隆对象
如何在 .Net(特别是 C#)中对对象进行深度复制?

Object.MemberwiseClone如果您不需要深拷贝,您也可以使用:

public class SaveData : ICloneable
{
    public double save_property1;
    public double save_property2;    

    public object Clone()
    {
        return this.MemberwiseClone();
    }
}

接着:

if (some condition 2) 
{
    SaveData copySaveData = newSaveData.Clone();
    copySaveData.save_property2 = y;
    newSaveDataList.Add(copySaveData);
}

或其他方式:

if (some condition 2) 
{
    newSaveData.save_property2 = y;
    newSaveDataList.Add(newSaveData);
    newSaveData = newSaveData.Clone();
    // from now on all the new changes will happen to a new object, not the one in the list.
}
于 2012-10-26T13:55:10.883 回答