Was ist der Unterschied zwischen dem System.Array.CopyTo()
und System.Array.Clone()
?
Was ist der Unterschied zwischen dem System.Array.CopyTo()
und System.Array.Clone()
?
Antworten:
Die Clone () -Methode gibt ein neues Array-Objekt (eine flache Kopie) zurück, das alle Elemente im ursprünglichen Array enthält. Das CopyTo () -Methode kopiert die Elemente in ein anderes vorhandenes Array. Beide führen eine flache Kopie durch. Eine flache Kopie bedeutet, dass der Inhalt (jedes Array-Element) Verweise auf dasselbe Objekt enthält wie die Elemente im ursprünglichen Array. Eine tiefe Kopie (die keine dieser Methoden ausführt) würde eine neue Instanz des Objekts jedes Elements erstellen, was zu einem anderen, aber identischen Objekt führen würde.
Der Unterschied ist also:
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.
Bearbeiten:
Entfernen Sie das falsche Beispiel.
numbersCopy
ist nur ein weiterer Verweis auf das Array zugeordnet numbers
. Dies ist nicht dasselbe wie die Verwendung der CopyTo()
Methode. Wenn Sie verwenden CopyTo()
, erhalten Sie die gleichen Ergebnisse wie in Ihrem Clone()
Beispiel. Auch das ist C # - System.out.println
sollte sein Console.WriteLine
.
array
mit Elementen A
, B
und C
. Wenn Sie eine flache Kopie davon erstellt array
und diese geändert haben A
, wird die Änderung sowohl im Original als auch in der Kopie angezeigt. Wenn Sie eine tiefe Kopie erstellt hätten, hätten Sie völlig andere Objekte, und dies würde nicht passieren (dies ist leichter zu verstehen, wenn Sie über gute Kenntnisse in Bezug auf Zeiger und Referenzen im Vergleich zu Werten in der Programmierung verfügen).
Ein weiterer Unterschied, der bisher nicht erwähnt wurde, ist der folgende
Clone()
dem Ziel-Array muss noch nicht vorhanden sein, da ein neues von Grund auf neu erstellt wird.CopyTo()
nicht nur entbindet der Ziel - Array bereits existiert, muss es groß genug , um alle Elemente in dem Quell - Array aus dem Index , den Sie als Ziel angeben , zu halten.Wie in vielen anderen Antworten angegeben, führen beide Methoden flache Kopien des Arrays durch. Es gibt jedoch Unterschiede und Empfehlungen, die noch nicht angesprochen wurden und die in den folgenden Listen hervorgehoben werden.
Eigenschaften von System.Array.Clone
:
CopyTo
wahrscheinlich, weil es verwendet wird Object.MemberwiseClone
.Eigenschaften von System.Array.CopyTo
:
Clone
beim Kopieren in ein Array des gleichen Typs;Array.Copy
erfordert das Erben von Fähigkeiten , die am nützlichsten sind:
int[]
Arrays in ein object[]
;object[]
Arrays von Boxen int
in ein int[]
;int[]
in a long[]
.Stream[]
Arrays in ein MemoryStream[]
(wenn ein Element im Quellarray nicht in MemoryStream
eine Ausnahme konvertierbar ist, wird ausgelöst).Beachten Sie auch , sind diese Verfahren zur Verfügung zu unterstützen ICloneable
und ICollection
, wenn Sie also mit Variablen von Array - Typen handelt , sollten Sie nicht verwenden Clone
oder CopyTo
stattdessen verwenden Array.Copy
oder Array.ConstrainedCopy
. Die eingeschränkte Kopie stellt sicher, dass der Status des Zielarrays nicht beschädigt wird, wenn der Kopiervorgang nicht erfolgreich abgeschlossen werden kann.
.ToArray()
Methode verwenden. Es erstellt ohnehin eine Kopie und kann auf allen IEnumerable<>
Arrays ausgeführt werden , einschließlich Arrays. Und im Gegensatz dazu .Clone()
ist es getippt, so dass kein Casting erforderlich ist.
Beide führen flache Kopien durch, wie @PatrickDesjardins sagte (trotz der vielen irregeführten Seelen, die denken, dass CopyTo
dies eine tiefe Kopie ist).
Sie CopyTo
können jedoch ein Array in einen angegebenen Index im Zielarray kopieren, wodurch die Flexibilität erheblich erhöht wird.
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"
Sowohl CopyTo () als auch Clone () erstellen eine flache Kopie. Die Clone () -Methode erstellt einen Klon des ursprünglichen Arrays. Es wird ein Array mit exakter Länge zurückgegeben.
Andererseits kopiert CopyTo () die Elemente aus dem ursprünglichen Array in das Zielarray, beginnend mit dem angegebenen Zielarrayindex. Beachten Sie, dass dadurch Elemente zu einem bereits vorhandenen Array hinzugefügt werden.
Der folgende Code widerspricht den Postings, die besagen, dass CopyTo () eine tiefe Kopie erstellt:
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);
}
Lassen Sie es mich ein wenig erklären. Wenn die Elemente des Arrays vom Referenztyp sind, wird die Kopie (sowohl für Clone () als auch für CopyTo ()) bis zur ersten (obersten) Ebene erstellt. Die untere Ebene wird jedoch nicht kopiert. Wenn wir auch eine Kopie der unteren Ebene benötigen, müssen wir dies explizit tun. Aus diesem Grund verweist nach dem Klonen oder Kopieren von Elementen vom Referenztyp jedes Element im geklonten oder kopierten Array auf denselben Speicherort, auf den sich das entsprechende Element im ursprünglichen Array bezieht. Dies zeigt deutlich an, dass keine separate Instanz für eine niedrigere Ebene erstellt wurde. Wenn dies der Fall wäre, hätte das Ändern des Werts eines Elements im kopierten oder geklonten Array keine Auswirkungen auf das entsprechende Element des ursprünglichen Arrays.
Ich denke, meine Erklärung ist erschöpfend, aber ich habe keinen anderen Weg gefunden, sie verständlich zu machen.
Array.Clone()
würde eine technisch tiefe Kopie durchführen, wenn das Array int
oder die Zeichenfolge als Referenz an eine Methode übergeben wird.
Beispielsweise
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
Selbst wenn die Methoden das Zahlenarray sortieren, dies jedoch keinen Einfluss auf die tatsächliche Referenz hat, die an die Sortiermethoden übergeben wird. Das Zahlenarray hat in Zeile 1 das gleiche unsortierte Anfangsformat.
Hinweis: Das Klonen sollte in den Sortiermethoden erfolgen.
Die Clone()
Methode gibt keinen Verweis auf die Zielinstanz, sondern gibt Ihnen nur eine Kopie. Die CopyTo()
Methode kopiert die Elemente in eine vorhandene Instanz.
Beide geben nicht die Referenz der Zielinstanz an und da viele Mitglieder sagen, dass sie eine flache Kopie (Illusionskopie) ohne Referenz geben, ist dies der Schlüssel.
Die Antworten sind für mich verwirrend. Wenn Sie flache Kopie sagen, bedeutet dies, dass sie immer noch auf dieselbe Adresse zeigen. Das heißt, wenn Sie eines der beiden ändern, ändert sich auch das andere.
Wenn ich also A = [1,2,3,4] habe und es klone und B = [1,2,3,4] erhalte. Wenn ich nun B [0] = 9 ändere, bedeutet dies, dass A jetzt A = [9,2,3,4] ist. Ist das korrekt?
Beide sind flache Kopien. Die CopyTo-Methode ist keine tiefe Kopie. Überprüfen Sie den folgenden Code:
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 */
Für Array.Clone muss beim Aufrufen der Funktion kein Ziel- / Zielarray verfügbar sein, während für Array.CopyTo ein Zielarray und ein Index erforderlich sind.
Clone()
wird verwendet, um nur die Struktur von Daten / Arrays zu kopieren. Es werden nicht die tatsächlichen Daten kopiert.
CopyTo()
kopiert die Struktur sowie die tatsächlichen Daten.
Bitte beachten Sie: Es gibt einen Unterschied zwischen der Verwendung von String [] und StringBuilder [].
In String - Wenn Sie den String ändern, ändern sich die anderen Arrays, die wir kopiert haben (von CopyTo oder Clone) und die auf denselben String verweisen, nicht. Das ursprüngliche String-Array zeigt jedoch auf einen neuen String, wenn wir einen StringBuilder verwenden In einem Array ändert sich der String-Zeiger nicht. Daher wirkt er sich auf alle Kopien aus, die wir für dieses Array erstellt haben. Zum Beispiel:
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 zu tun Clone
. Es ist nur Referenzsemantik gegen Wertesemantik. int ist ein Werttyp, sodass Sie jedes Mal eine neue Kopie erhalten. StringBuilder verfügt über eine Referenzsemantik, sodass Sie auf dieselbe Kopie reagieren.