列出持有参考

时间:2012-10-26 13:42:51

标签: c#

我有一个对象(我创建的类)的List(在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 个答案:

答案 0 :(得分:5)

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

请记住,当您向列表添加引用类型时,您只需将reference放入列表而不是引用的对象。这意味着如果你总是推送同一个实例,所有&#34;项目&#34;在列表中是真的相同的项目。考虑:

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);  
    }
}

以上假设每个对象都是不同的,而不是飞行中的对象&#34;跨越循环的多次迭代。

现在,如果你有一个主要对象,而你只是试图放一个&#34;快照&#34;在列表中的那个对象,您可以使用某种克隆方法或&#34;复制构造函数&#34;各种各样:

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;
    }
}

然后,如果你想在飞行中的物体列表上放一个snapshot,你可以这样做:

newSaveDataList.Add(new SaveData(newSaveData));

或者,您可以使用struct而不是值类型,因此会在列表中放置副本,但struct有很多有趣的怪癖,在使用它们之前应该仔细考虑它们。我有关于此主题的帖子here

答案 1 :(得分:2)

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

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

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

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

    ...

    history.Add(sd);
}

答案 2 :(得分: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);
}

答案 3 :(得分:0)

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

看看这两个问题:

Cloning objects in C#
How do you do a deep copy an object in .Net (C# specifically)?

如果您不需要深层复制,也可以使用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.
}