2009-05-10 9 views
1

IEnumerableを受け入れるコレクションにコンストラクタがあります。私はアイテムを使って新しいコレクションを列挙して作成したいが、同じアイテムは参照しない。項目には値型と参照型を指定できます。refタイプ(deepcopy)のコピー方法は?

CustomCollection cc = new CustomCollection (IEnumerable<T> items) 
{ 
    foreach (var item in items) 
    { 
     this.Add(item); // justs adds the reference for ref types. 
    } 
} 

EDIT:.NETコレクションには同じメソッドがあり、ディープコピーは行いません。なぜ元のコレクションと同じ要素を参照するコレクションを持たせたいのですか?

答えて

-2

できません。すべてのオブジェクトがクローンのようなメソッドをサポートするわけではありません。

0

あなたのアイテムがIClonableインターフェイス(インターフェイス関数の正しい実装で)をサポートしていれば、深いコピーを作成する.clone関数を呼び出すことができると思います。

+1

ICloneableはあまり指定されておらず(浅いまたは深いとマークされていない)、ほとんどサポートされていません。 –

3

問題のクラスがシリアル化をサポートしている場合は、コレクションを一時ストリームにシリアル化し、逆シリアル化して新しいコレクションに戻すことができます。

いくつかのクラスはICloneableをサポートしていますが、正確にはプログラマが決めることができます。それは深いコピーかもしれない、そうでないかもしれない。

もちろん、すべてのクラスがシリアライゼーションやクローニングをサポートしているわけではありませんので、必要なものはすべてのタイプで行うことはできません。

これを機能させるには、いくつかの制限を設定する必要があります。

2

オブジェクトはシリアライズされている場合は、このような深いコピーすることができます:

private object GetCopy(object original) 
{ 
    if (original == null) 
    { 
     return null; 
    } 

    object result; 
    using (MemoryStream stream = new MemoryStream()) 
    { 
     BinaryFormatter formatter = new BinaryFormatter(); 
     formatter.Serialize(stream, original); 
     stream.Position = 0; 
     result = formatter.Deserialize(stream); 
     stream.Close(); 
    } 
    return result; 
} 
+0

うん、私は同じものをコピーして貼り付けることができた。あなたはそれらを深くクローンする必要があります。またはあなたは同じ参照を指しています。 – Chris

+0

@Chris:申し訳ありませんが、私はあなたのコメントを理解していません。上記のコードは、私が現在働いているプロジェクトから来ています(キャッシュからオブジェクトのコピーを取得する場合に使用します)。コードはディープコピーメカニズムを提供します。返されたオブジェクトは元のオブジェクトから完全に切り離されます。 –

-2

は、私はそれで多くのことを働いていないとして、構文を知らないが、潜在的に可能性がありません。このリフレクションでやる?私は反射が、一般的にパフォーマンスヒットを招き実現する、しかし、あなたは、次のようなものをスイッチケースの事のいくつかの並べ替えを行うことができるかもしれない:

(擬似コード)

if(item.isValueType) { 
    newCol.Add(item) 
} elseif(item.isRefType && item.SupportsICloneable) { 
    newCol.Add(item.clone()) 
} else { 
    doReflectionCopy() 
} 

あなたはまた、コードを追加することもできますシリアル化可能なチェックのために、Frederikのメソッドが含まれています。

0

ディープコピーを実行する効果は大きく異なります。そのため、ディープコピーはCLRによって自動的には提供されません。例えば、ディープ・コピーが、SQL管理ソケット、ソケット、カスタムGDIブラシなどのOS管理リソースへのハンドルを保持しているオブジェクトを複製した場合の状況を想像してみてください。

実際には、上記のような方法を採用する必要があります。あなたがソースがインターフェイスを適切に実装することを信じていると思うなら、TがICloneableかどうかを調べてください。そうでない場合(ソースを信頼するか、またはTが複製可能でない場合)、オブジェクトがISerializableとマークされているか、SerializableAttributeを持っているかどうかをチェックし、新しいオブジェクトにシリアライズ/デシリアライズします。

Tがクローン可能でもシリアライズ可能でもない場合は、例外をスローして詳細コピーを作成しないでください。

関連する問題