0

だから私はリストを持っており、私のメソッドでは変更を加えた新しいリストを返そうとしています。

ただし、問題は、手がかりのリストの Id に加えた変更が、渡す手がかりのリストにも加えられることです。

        public List<Clue> NewOrderList(List<Clue> clues, int[] ids)
    {
        var newClueOrder = new List<Clue>();

        // For each ID in the given order
        for (var i = 0; i < ids.Length; i++)
        {
            // Get the original clue that matches the given ID
            var clue = clues.First(clue1 => clue1.Id == ids[i]);

            // Add the clue to the new list. 
            newClueOrder.Add(clue);

            // Retain the ID of the clue 
            newClueOrder[i].Id = clues[newClueOrder.Count - 1].Id;
        }

        return newClueOrder;
    }

これはなぜですか? また、これに対する最善の解決策は何ですか? 同様の質問を見たことがありますが、正直なところ、解決策が正確に何であるかはよくわかりませんでした。

4

2 に答える 2

2

あなたは浅いコピーを作成しています。リストのディープコピーが必要なようです。したがって、最初にディープ コピーを作成してから、変更が必要なものをすべて変更して、新しいリストを返します。

リストをシリアル化および逆シリアル化して、ディープ コピーを作成できます。

リストのディープ コピーを作成すると、浅いコピーのようにそれらを参照するだけでなく、新しい手がかりオブジェクトが作成されます。

   public List<Clue> NewOrderList(List<Clue> clues)
   {
        List<Clue> newstringOrder = CreateDeepCopy(clues);

        // Add code to modify list

        return newstringOrder;
   }


public List<Clue> CreateDeepCopy(List<Clue> c)
{
     //Serialization    
     if(c == null)
            return null;
     BinaryFormatter bf = new BinaryFormatter();
     MemoryStream ms = new MemoryStream();
     bf.Serialize(ms, c);

     //Deserialization              
     ms.Position = 0;        
     List<Clue> list = (List<Clue>)bf.Deserialize(ms);       

     return list;    

}
于 2013-04-25T01:15:35.177 に答える
1

Clue参照型だからです。新しいClueインスタンスを作成するのではなく、実際には既存のインスタンスを変更しています。

これを回避するには、コピー コンストラクターまたはある種のクローンを使用してディープ コピーを取得します。

        // Get the original clue that matches the given ID
        var clue = clues.First(clue1 => clue1.Id == ids[i]);

        // Copy constructor
        var newClue = new Clue(clue);

        // Or, use cloning
        var newClue = clue.Clone();

        // Add the clue to the new list. 
        newClueOrder.Add(newClue);

        // Retain the ID of the clue 
        newClueOrder[i].Id = clues[newClueOrder.Count - 1].Id;

or コピー コンストラクターではClone()、参照を再割り当てするだけでなく、他のすべての不変参照型のコピーを作成する必要があります。たとえば、Clue が次のものを持っていると仮定します。

public class Clue
{
    ...

    public Clue Clone()
    {
        Clue newClue = new Clue();
        newClue.SomeClassType = this.SomeClassType.Clone(); // You'll need to get a clone or copy of all non-immutable class members as well.
        newClue.Id = this.Id;  // Value types are copied by value, so are safe to assign directly.
        newClue.Name = this.Name;  //If Name is a string, then this is safe too, since they are immutable.
        return newClue;
    }
}
于 2013-04-25T01:15:27.083 に答える