2012-04-28 3 views
0

私はカスタムクラスのオブジェクトのリストを持っているクローンだ編集します元の(URL)リストからオブジェクトを削除します。スタック(temp)上のものはすべてOKです。しかし、元のオブジェクト(URL)内のリストからリスト要素を削除すると、同じ要素がそのオブジェクトのリストのコピー内に消えてしまいます。編集つのリストは、<>それは

オブジェクトをURLから削除するのは、そのオブジェクト内のリスト要素を削除するのと同じ方法です。 これはなぜ起こっているのですか?

答えて

1

リストは基本的に配列、つまり参照型です。彼らはお互いの参照のみを持っています。

拡張メソッド

public static class ExtensionMethod 
{ 
    public static T DeepClone<T>(this T element) 
    { 
     MemoryStream m = new MemoryStream(); 
     BinaryFormatter b = new BinaryFormatter(); 
     b.Serialize(m, element); 
     m.Position = 0; 
     return (T)b.Deserialize(m); 
    } 
} 

を使用してディープコピーを作成し、uはこの

[Serializable] 
public class URL 
{ 
    //..... Your Class 
} 

のようなあなたのURLクラスを宣言し、作成必要

temp.AddRange(URLs.DeepClone().ToList()); 
+0

よく、このアイデアをどのように修正するのですか? – Igor

+0

@Igor深いクローンを作る –

+0

そして最初の部分はどこに置くのですか?どこかクラス内で? – Igor

0

ようにそれを呼び出すことを確認してくださいクローン

static class Extensions 
{ 
     public static IList<T> Clone<T>(this IList<T> listToClone) where T: ICloneable 
     { 
       return listToClone.Select(item => (T)item.Clone()).ToList(); 
     } 
} 
+0

*クローンを作成するリスト内の各項目の – abatishchev

0

リストまたはスタックには、そのオブジェクトに含まれる参照の参照のみが保持されます。どちらのリストも同じオブジェクトへの参照を保持しています。したがって、あるリストから到達したオブジェクトを変更すると、それは他のリストから到達したオブジェクトと同じです。

@simply denisは、2番目のリストを作成するときにオブジェクトをクローンすることができるので、各リストにオブジェクトのコピーがあるようにすることができます。

もう1つの解決策は、不変オブジェクトを使用することです。たとえば、.NETのstringクラスは不変です。文字列を作成したら、それを変更することはできません。すべての文字列操作ルーチンは新しい文字列を返します。不変型は、操作が自動的に新しいインスタンスを作成するため、この種の問題を効果的に防ぎます。

+0

immutableは、C#で多くの種類の不変性があるため、ここでは危険な言葉です(例えば、参照オブジェクトの読み込みスタックは変更できませんが、アイテムは変更可能です)。より適切には、元のポスターは値の型彼らのコレクションのアイテムとして。 – Sprague

+0

.NETの値型(組み込み関数または 'struct')は常に不変ですが、不変の文字列型もあります。例えば。 'string'の[MSDN doc](http://msdn.microsoft.com/en-us/library/362314fe.aspx)はimmutableという用語を使用します*文字列は不変です - 文字列オブジェクトの内容は変更できません* –

+0

私は単純に、C#での不変性に問題があることを指摘しています。不変型を使用すると、元のポスターの問題は必ずしも解決されず、より深いパスに導かれます。さらに重要なことに、OPはオブジェクト参照がどのように機能するのか、なぜこれが彼の問題の本当の原因であるのかを理解する必要があります。 – Sprague

0

これは、リストの浅いコピーを作成しているためです。同じURLオブジェクトへの参照を持つ2つのリストが表示されます。

は(あなただけから読み取られ、その後、捨てた、あなたは、実際には2つの浅いコピーを作っている、new List<URL>(URLs)は中間コピーを作成することに注意してください。)

あなたは深いコピーをしたい場合は、新しいURLを作成する必要がありますコピーのインスタンス。私は基本的にあなたがURLクラスに実装されているものを知らない:

List<URL> temp = new List<URL>(URLs.Select(u => u.Clone())); 
+0

これでクラスが追加されました。具体的には、 – Igor

+0

@Igor:Ow、that効率的ではありません...既存のもののコピーをコピーすることによって、 'URL'の新しいインスタンスを作成するメソッドが必要であり、オブジェクトのリストの完全なコピーを作成する必要があります。 Nikhilが示唆しているようにシリアライズを使用することはできますが、これはあまり効率的ではありません。そのためにはパラメーターなしのコンストラクターが必要です。 – Guffa

0

でURLオブジェクトがのURLでそれらのURLオブジェクトと同じオブジェクトを参照されを元に戻すためです。したがって、それを変更すると別のものに影響します。あなたがする必要があるのは、URLオブジェクトの深いコピーを作ることです。ディープコピーを作成する方法は、実際にはURLクラスの実装に依存します。 How do you do a deep copy of an object in .NET (C# specifically)?

URLオブジェクトを複製するには、より効率的な方法があります。クラスの実装を最初に示す必要があります。

+0

'新しい'コンストラクタは、ここで言及するのではなく、新しいリストを作成しません:temp.AddRange(new List (URL)); – Igor

関連する問題