Arasındaki fark nedir System.Array.CopyTo()
ve System.Array.Clone()
?
Arasındaki fark nedir System.Array.CopyTo()
ve System.Array.Clone()
?
Yanıtlar:
Klon () metodu yeni bir dizi orijinal dizideki tüm elemanları ihtiva eden (basit bir kopyasını) nesnesini geri gönderir. CopyTo () metodu kopya olan başka bir diziye elemanları. Her ikisi de sığ bir kopya oluşturur. Yüzeysel kopya, içeriklerin (her dizi öğesi) orijinal dizideki öğelerle aynı nesneye referanslar içerdiği anlamına gelir. Derin bir kopya (bu yöntemlerden hiçbirinin gerçekleştirmediği), her bir öğenin nesnesinin yeni bir örneğini oluşturarak farklı, ancak aynı bir nesne ortaya çıkarır.
Yani fark:
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.
Düzenle:
Yanlış örneği kaldırın.
numbersCopy
atanan diziye başka bir referanstır numbers
. Bu, yöntemi kullanmakla aynı şey değildirCopyTo()
. Eğer kullanırsanız CopyTo()
, Clone()
örneğinizdekiyle aynı sonuçları alırsınız . Ayrıca, bu C # - System.out.println
olmalıdır Console.WriteLine
.
ToArray()
yöntemi zaten bir diziyi sığ klonlamanın çok daha basit (ve tiplenmiş ) bir yolunu sağlar. Dizi olduğu IENumerable<T>
için üzerinde çalışıyor.
Şimdiye kadar belirtilmeyen bir diğer fark ise
Clone()
bir yenisi sıfırdan oluşturulur beri hedef dizisi ihtiyacı yok henüz var.CopyTo()
zaten hedef dizisi ihtiyacı ortadan yok kalmaz aynı hedef olarak belirtmek dizinden kaynak dizideki tüm elemanları tutmaya yeterli büyüklükte olması gerekir.Diğer birçok cevapta belirtildiği gibi, her iki yöntem de dizinin yüzeysel kopyalarını gerçekleştirir . Ancak, henüz ele alınmamış ve aşağıdaki listelerde vurgulanan farklılıklar ve öneriler vardır.
Özellikleri System.Array.Clone
:
CopyTo
göstermektedir Object.MemberwiseClone
;Özellikleri System.Array.CopyTo
:
Clone
Aynı türden diziye kopyalamadan daha hızlıdır ;Array.Copy
En kullanışlı olan yeteneklerden miras almaya çağırır :
int[]
diziyi bir object[]
;object[]
kutulu diziyi int
bir int[]
;int[]
bir long[]
.Stream[]
diziyi a'ya kopyalamak MemoryStream[]
(kaynak dizideki herhangi bir öğe MemoryStream
bir istisnaya dönüştürülemiyorsa ).Ayrıca, bu yöntemlerin desteklenmesi için sağlandığını ICloneable
ve ICollection
bu nedenle dizi türlerinin değişkenleriyle uğraşıyorsanız, kullanmamalısınız Clone
veya CopyTo
bunun yerine Array.Copy
veya kullanmalısınız Array.ConstrainedCopy
. Kısıtlı kopya, kopyalama işlemi başarılı bir şekilde tamamlanamazsa hedef dizi durumunun bozulmamasını sağlar.
.ToArray()
yöntemini kullanabilirsiniz . Yine de bir kopya oluşturur ve IEnumerable<>
diziler dahil herhangi bir yerde çalıştırılabilir . Ve aksine .Clone()
, yazılmıştır, bu nedenle döküm gerekmez.
Her ikisi de @ PatrickDesjardins'in dediği gibi sığ kopyalar yapıyor (bunun CopyTo
derin bir kopya olduğunu düşünen birçok yanlış yönlendirilmiş ruha rağmen ).
Ancak, CopyTo
bir diziyi hedef dizideki belirli bir dizine kopyalamanıza izin vererek, ona önemli ölçüde daha fazla esneklik sağlar.
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"
Hem CopyTo () hem de Clone () sığ kopya oluşturur. Clone () yöntemi, orijinal dizinin bir klonunu oluşturur. Tam uzunlukta bir dizi döndürür.
Öte yandan, CopyTo (), öğeleri orijinal diziden, belirtilen hedef dizi dizininden başlayarak hedef diziye kopyalar. Bunun zaten var olan bir diziye eleman eklediğini unutmayın.
Aşağıdaki kod, CopyTo () öğesinin derin bir kopya oluşturduğunu söyleyen kayıtlarla çelişecektir:
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);
}
Biraz açıklayayım. Dizinin öğeleri başvuru türlerindeyse, kopya (hem Clone () hem de CopyTo () için) birinci (üst) seviyeye kadar oluşturulacaktır. Ancak alt düzey kopyalanmaz. Alt seviyenin kopyasına da ihtiyacımız varsa, bunu açıkça yapmalıyız. Referans tipi elemanların Klonlanmasından veya Kopyalanmasından sonra, Cloned veya Copied dizisindeki her eleman, orijinal dizideki karşılık gelen eleman tarafından atıfta bulunulan aynı bellek konumuna başvurur. Bu, daha düşük seviye için ayrı bir örneğin oluşturulmadığını açıkça gösterir. Ve eğer öyleyse, Kopyalanmış veya Klonlanmış dizideki herhangi bir öğenin değerini değiştirmek, orijinal dizinin karşılık gelen öğesi üzerinde etkili olmayacaktır.
Açıklamamın kapsamlı olduğunu düşünüyorum, ancak bunu anlaşılır kılmanın başka bir yolunu bulamadım.
Array.Clone()
dizi int
veya dizeyi referans olarak bir yönteme iletirken teknik olarak derin kopyalama gerçekleştirir .
Örneğin
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
Yöntemler sayı dizisini sıralasa, ancak sıralama yöntemlerine iletilen gerçek referansı etkilemeyecek olsa bile, sayı dizisi 1 numaralı satırda aynı sıralanmamış başlangıç biçiminde olacaktır.
Not: Klonlama, sıralama yöntemlerinde yapılmalıdır.
Clone()
Yöntem sadece size bir kopyasını vermek hedef örneğine referans vermezler. CopyTo()
yöntem kopyalar mevcut bir örneğine elemanları.
Her ikisi de hedef örneğin referansını vermez ve birçok üye referans olmadan sığ kopya (illüzyon kopyası) verdiklerini söylediği için anahtar budur.
Cevaplar kafamı karıştırıyor. Yüzeysel kopya dediğinizde, bu onların hala aynı adresi gösterdikleri anlamına gelir. Bu, birini değiştirmenin diğerini de değiştireceği anlamına gelir.
Yani eğer A = [1,2,3,4] varsa ve onu klonlarsam ve B = [1,2,3,4] elde edersem. Şimdi, eğer B [0] = 9'u değiştirirsem. Bu, A'nın artık A = [9,2,3,4] olacağı anlamına gelir. Bu doğru mu?
Her ikisi de sığ kopyalar. CopyTo yöntemi derin bir kopya değildir. Aşağıdaki kodu kontrol edin:
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 */
Array.Clone , işlev çağrılırken bir hedef / hedef dizisinin kullanılabilir olmasını gerektirmezken , Array.CopyTo bir hedef dizi ve bir dizin gerektirir.
Clone()
yalnızca veri / dizi yapısını kopyalamak için kullanılır, gerçek verileri kopyalamaz.
CopyTo()
yapıyı ve gerçek verileri kopyalar.
Lütfen dikkat: String [] kullanımı ile StringBuilder [] arasında bir fark vardır.
String'de - String'i değiştirirseniz, kopyaladığımız ve aynı dizeyi gösteren diğer diziler (CopyTo veya Clone ile) değişmeyecek, ancak orijinal String dizisi yeni bir String'i gösterecek, ancak bir StringBuilder kullanırsak bir dizide, String işaretçisi değişmeyecek, bu nedenle bu dizi için yaptığımız tüm kopyaları etkileyecektir. Örneğin:
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 ile ilgili değildir Clone
. Bu sadece referans anlambilim ve değer anlambilimidir. int bir değer türüdür, bu nedenle her seferinde yeni bir kopya alırsınız. StringBuilder'ın referans semantiği vardır, bu nedenle aynı kopya üzerinde hareket ediyorsunuz.