2009-07-31 6 views
13

私は型付き配列MyType[] types; を持っていますが、私はこの配列を独立してコピーしたいと思います。私はこれを試したC#値で配列をコピー

MyType[] types2 = new MyType[types.Length] ; 

types2 = types ; 

しかし、これは最初のものへの参照を作成します。私はそれを試みた

Array.Copy(types , types2 , types.Length) ; 

私は同じ問題があります:最初の配列の値を変更すると、コピーの値も変更されます。

Array、IListまたはIEnumerableの完全に独立した、またはディープコピーを作成するにはどうすればよいですか?

答えて

9

保護されたメソッドMemberwiseClone(浅いコピーを実行する)または深いクローン技術を使用して、MyTypeでクローンメソッドを実装します。 ICloneableを実装してから、対応するコレクションを複製するいくつかの拡張メソッドを記述することができます。

interface ICloneable<T> 
{ 
    T Clone(); 
} 

public static class Extensions 
{ 
    public static T[] Clone<T>(this T[] array) where T : ICloneable<T> 
    { 
     var newArray = new T[array.Length]; 
     for (var i = 0; i < array.Length; i++) 
      newArray[i] = array[i].Clone(); 
     return newArray; 
    } 
    public static IEnumerable<T> Clone<T>(this IEnumerable<T> items) where T : ICloneable<T> 
    { 
     foreach (var item in items) 
      yield return item.Clone(); 
    } 
} 

Array.Copyを使用するときに新しい配列が作成されている間は、参照されたオブジェクトではなく参照がコピーされるため、これを行う必要があります。それぞれのタイプは、それ自身をコピーする責任があります。

+1

マイクロソフトが言うようになります。 .110).aspx)深い対浅いコピーのセマンティクスを指定していないためです。独自のIDeepCopyableインターフェイスを作成する方が効果的です。 – Wilbert

11

最初の投稿に基づいて、彼が必要とするのは、「配列の独立したコピー」です。 shallowCopy配列自体への変更はtypes配列には表示されません(実際には "ディープコピー"と言っても上に示したものです)。これがあなたのニーズに合っていれば、最高のパフォーマンスを発揮します。

MyType[] shallowCopy = (MyType[])types.Clone(); 

彼はまた、プリミティブの再帰的な値型の集合体ではありません可変タイプごとに異なるだろう「ディープコピー」を言及しています。 MyTypeICloneableを実装する場合、これは深いコピーのための素晴らしい作品:

MyType[] deepCopy = (MyType[])Array.ConvertAll(element => (MyType)element.Clone()); 
6

あなたのタイプが直列化可能である場合は、(項目の深いコピーを含む)あなたの配列のコピーを取得するには、シリアル化技術を使用することができます。

それを使用するに
private static object GetCopy(object input) 
{ 
    using (MemoryStream stream = new MemoryStream()) 
    { 
     BinaryFormatter formatter = new BinaryFormatter(); 
     formatter.Serialize(stream, input); 
     stream.Position = 0; 
     return formatter.Deserialize(stream); 
    } 
} 

MyType[] items = new MyType[2]; 
// populate the items in the array 

MyType[] copies = (MyType[])GetCopy(items); 
+0

私の型はシリアライズ可能ではありません=( – JOBG

+0

これは甘いです!!! –

3

私は同じことやってみたかった:私はリットルができるように、並べ替えのようなもののための値で、配列のコピーを作成します元のソース配列で別の一時配列を再初期化します。これを研究した後、私はこれを単純に行うことができないことを発見しました。だから、私は回避策をとった。

string[] planetNames = new string[] { "earth", "venus", "mars" }; 

string[] tempNames = new string[planetNames.Length]; 

for (int i = 0; i < planetNames.Length; i++) 
{ 
    tempNames[i] = planetNames[i]; 
} 

planetNamesが私の元配列である:私は以下の私自身のコードを使用します。 tempNamesは、後でplanetNamesから独立してソートする配列です。私はこれをテストしましたが、このコードは並べ替えられませんplanetNames私はtempNamesをソートすると、これは私が達成しようとしていたものです。あなただけの単純なchar型の配列をしたい場合は、私が見つけた

0

あなたは文字を使用して値によってコピーを行うにC#のをだますことができますコピー:

char[] newchararray = new char[desiredchararray.Length]; 

for (int k = 0; k < desiredchararray.Length; k++) 
{ 

    char thecharacter = newchararray[k]; 
    newchararray[k] = thecharacter; 
    oldchararray[k] = oldchararray[k] + 1; 

} 

は私のために動作するようですが、誰もが同意しない場合は、私を聞かせてください知っている:)

+2

charは値型です – Odrade

7

せっかちについて:

newarray = new List<T>(oldarray).ToArray(); 
1

あなただけの古い配列内のオブジェクトへの参照を含む配列(またはあなたが値型のオブジェクトの配列を持っている場合)のコピーを作成したい場合、最も簡単な解決策は、あなたが深いコピーをしたい場合は、あなたがあなたのタイプのコピーを単一のオブジェクト(例えばメソッドを持っている必要があり

var newArray = oldArray.ToArray() 

ですpublic MyType Copy(MyType obj))。 [我々はICloneableは公開APIで実装されていないことをお勧めします](http://msdn.microsoft.com/en-us/library/system.icloneable(V = VS:次いで、溶液を

var newArray = oldArray.Select(x => Copy(x)).ToArray() 
+0

明確にするために、 'Copy(x)'はカスタム実装です、右ですか? – Thor

+1

はい、オブジェクトの完全コピーを行う方法はありません。[MemberwiseClone](https://msdn.microsoft.com/en-us/library/system.object.memberwiseclone(v = vs.110).aspx )メソッドは保護され、深いコピーではなく、浅いコピー(オブジェクト自体のコピーですが、参照型のフィールドの新しいコピーを作成しません)のみを作成します。 – renadeen

関連する問題