違いは何だSystem.Array.CopyTo()
とはSystem.Array.Clone()
?
違いは何だSystem.Array.CopyTo()
とはSystem.Array.Clone()
?
回答:
クローン()メソッドは、元の配列内のすべての要素を含む新しい配列(浅いコピー)オブジェクトを返します。CopyToの()メソッド別の既存の配列にコピーする要素。どちらも浅いコピーを実行します。浅いコピーとは、コンテンツ(各配列要素)に元の配列の要素と同じオブジェクトへの参照が含まれていることを意味します。ディープコピー(これらのメソッドはどちらも実行されません)は、各要素のオブジェクトの新しいインスタンスを作成し、異なるが同一のオブジェクトになります。
したがって、違いは次のとおりです。
1- CopyTo require to have a destination array when Clone return a new array.
2- CopyTo let you specify an index (if required) to the destination array.
編集:
間違った例を削除してください。
numbersCopy
は、に割り当てられた配列への単なる別の参照numbers
です。これは、メソッドを使用することと同じではありませんCopyTo()
。を使用するとCopyTo()
、Clone()
例と同じ結果が得られます。また、これはC#です-するSystem.out.println
必要がありますConsole.WriteLine
。
ToArray()
メソッドは、とにかく配列を浅くクローンするはるかに簡単な(そして型指定された)方法を提供します。配列なので、それでIENumerable<T>
動作します。
他の多くの回答で述べられているように、どちらの方法も配列の浅いコピーを実行します。ただし、まだ対処されておらず、次のリストで強調表示されている違いと推奨事項があります。
CopyTo
おそらくObject.MemberwiseClone
;を使用しているためよりも遅いことが示されています。Clone
同じタイプの配列にコピーする場合よりも高速です。Array.Copy
機能である継承最も有用なものであること、:
int[]
配列をobject[]
;にコピーします。object[]
にボックスint
化解除できます。たとえば、ボックス化された配列をint[]
;にコピーします。int[]
しますlong[]
。Stream[]
配列をにコピーするなど、要素をダウンキャストできますMemoryStream[]
(ソース配列内のいずれかの要素がMemoryStream
例外に変換できない場合はスローされます)。また、これらのメソッドはICloneable
andをサポートできるICollection
ようになっているため、配列型の変数を扱う場合は、Clone
orCopyTo
を使用せず、代わりにorを使用するArray.Copy
必要がありArray.ConstrainedCopy
ます。制約付きコピーは、コピー操作が正常に完了できない場合でも、ターゲットアレイの状態が破損しないことを保証します。
.ToArray()
方法を使用できます。とにかくコピーを作成し、IEnumerable<>
配列を含む任意ので実行できます。そして、とは異なり.Clone()
、それはタイプされているので、キャストは必要ありません。
object[] myarray = new object[] { "one", 2, "three", 4, "really big number", 2324573984927361 };
//create shallow copy by CopyTo
//You have to instantiate your new array first
object[] myarray2 = new object[myarray.Length];
//but then you can specify how many members of original array you would like to copy
myarray.CopyTo(myarray2, 0);
//create shallow copy by Clone
object[] myarray1;
//here you don't need to instantiate array,
//but all elements of the original array will be copied
myarray1 = myarray.Clone() as object[];
//if not sure that we create a shalow copy lets test it
myarray[0] = 0;
Console.WriteLine(myarray[0]);// print 0
Console.WriteLine(myarray1[0]);//print "one"
Console.WriteLine(myarray2[0]);//print "one"
CopyTo()とClone()の両方が浅いコピーを作成します。Clone()メソッドは、元の配列のクローンを作成します。正確な長さの配列を返します。
一方、CopyTo()は、指定された宛先配列インデックスから開始して、元の配列から宛先配列に要素をコピーします。これにより、既存の配列に要素が追加されることに注意してください。
次のコードは、CopyTo()がディープコピーを作成するという投稿と矛盾します。
public class Test
{
public string s;
}
// Write Main() method and within it call test()
private void test()
{
Test[] array = new Test[1];
array[0] = new Test();
array[0].s = "ORIGINAL";
Test[] copy = new Test[1];
array.CopyTo(copy, 0);
// Next line displays "ORIGINAL"
MessageBox.Show("array[0].s = " + array[0].s);
copy[0].s = "CHANGED";
// Next line displays "CHANGED", showing that
// changing the copy also changes the original.
MessageBox.Show("array[0].s = " + array[0].s);
}
少し説明させてください。配列の要素が参照型の場合、コピー(Clone()とCopyTo()の両方)は最初の(トップ)レベルまで作成されます。ただし、下位レベルはコピーされません。下位レベルのコピーも必要な場合は、明示的に行う必要があります。そのため、参照型要素の複製またはコピー後、複製またはコピーされた配列の各要素は、元の配列の対応する要素によって参照されるのと同じメモリ位置を参照します。これは、下位レベル用に個別のインスタンスが作成されていないことを明確に示しています。その場合、コピーまたはクローン配列の要素の値を変更しても、元の配列の対応する要素には影響しません。
私の説明は網羅的だと思いますが、それを理解できるようにする他の方法は見つかりませんでした。
Array.Clone()
の配列int
または文字列を参照としてメソッドに渡すと、技術的に深いコピーが実行されます。
例えば
int[] numbers = new int[] { -11, 12, -42, 0, 1, 90, 68, 6, -9 };
SortByAscending(numbers); // Sort the array in ascending order by clone the numbers array to local new array.
SortByDescending(numbers); // Same as Ascending order Clone
メソッドが数値の配列を並べ替えても、並べ替えメソッドに渡される実際の参照には影響しません。つまり、数値配列は、1行目で同じ並べ替えられていない初期形式になります。
注:クローンは、並べ替え方法で実行する必要があります。
答えは私を混乱させます。浅いコピーと言うとき、これは彼らがまだ同じアドレスを指していることを意味します。つまり、どちらかを変更すると、もう一方も変更されます。
したがって、A = [1,2,3,4]があり、それを複製してB = [1,2,3,4]を取得した場合。ここで、B [0] = 9を変更すると、AはA = [9,2,3,4]になります。あれは正しいですか?
どちらも浅いコピーです。CopyToメソッドはディープコピーではありません。 次のコードを確認してください。
public class TestClass1
{
public string a = "test1";
}
public static void ArrayCopyClone()
{
TestClass1 tc1 = new TestClass1();
TestClass1 tc2 = new TestClass1();
TestClass1[] arrtest1 = { tc1, tc2 };
TestClass1[] arrtest2 = new TestClass1[arrtest1.Length];
TestClass1[] arrtest3 = new TestClass1[arrtest1.Length];
arrtest1.CopyTo(arrtest2, 0);
arrtest3 = arrtest1.Clone() as TestClass1[];
Console.WriteLine(arrtest1[0].a);
Console.WriteLine(arrtest2[0].a);
Console.WriteLine(arrtest3[0].a);
arrtest1[0].a = "new";
Console.WriteLine(arrtest1[0].a);
Console.WriteLine(arrtest2[0].a);
Console.WriteLine(arrtest3[0].a);
}
/* Output is
test1
test1
test1
new
new
new */
Clone()
データ/配列の構造のみをコピーするために使用され、実際のデータはコピーされません。
CopyTo()
構造と実際のデータをコピーします。
注意:String []とStringBuilder []の使用には違いがあります。
文字列内-文字列を変更すると、同じ文字列を指す(CopyToまたはCloneによって)コピーした他の配列は変更されませんが、元の文字列配列は新しい文字列を指しますが、StringBuilderを使用する場合配列では、文字列ポインタは変更されないため、この配列用に作成したすべてのコピーに影響します。例えば:
public void test()
{
StringBuilder[] sArrOr = new StringBuilder[1];
sArrOr[0] = new StringBuilder();
sArrOr[0].Append("hello");
StringBuilder[] sArrClone = (StringBuilder[])sArrOr.Clone();
StringBuilder[] sArrCopyTo = new StringBuilder[1];
sArrOr.CopyTo(sArrCopyTo,0);
sArrOr[0].Append(" world");
Console.WriteLine(sArrOr[0] + " " + sArrClone[0] + " " + sArrCopyTo[0]);
//Outputs: hello world hello world hello world
//Same result in int[] as using String[]
int[] iArrOr = new int[2];
iArrOr[0] = 0;
iArrOr[1] = 1;
int[] iArrCopyTo = new int[2];
iArrOr.CopyTo(iArrCopyTo,0);
int[] iArrClone = (int[])iArrOr.Clone();
iArrOr[0]++;
Console.WriteLine(iArrOr[0] + " " + iArrClone[0] + " " + iArrCopyTo[0]);
// Output: 1 0 0
}
CopyTo
vsとは関係ありませんClone
。これは、参照セマンティクスと値セマンティクスの違いです。intは値型であるため、毎回新しいコピーを取得します。StringBuilderには参照セマンティクスがあるため、同じコピーを操作しています。