Quelle est la différence entre System.Array.CopyTo()
et System.Array.Clone()
?
La méthode Clone () renvoie un nouvel object tableau (copie superficielle) contenant tous les éléments du tableau d’origine. La méthode CopyTo () copie les éléments dans un autre tableau existant. Les deux exécutent une copie superficielle. Une copie superficielle signifie que le contenu (chaque élément du tableau) contient des références au même object que les éléments du tableau d’origine. Une copie profonde (qu’aucune de ces méthodes n’effectue) créerait une nouvelle instance de l’object de chaque élément, produisant un object différent mais identique.
Donc la différence est:
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.
Modifier:
Supprimez le mauvais exemple.
Une autre différence non mentionnée jusqu’ici est que
Clone()
le tableau de destination n’existe pas encore car un nouveau est créé à partir de zéro. CopyTo()
non seulement le tableau de destination doit déjà exister, mais il doit être suffisamment grand pour contenir tous les éléments du tableau source de l’index que vous spécifiez comme destination. Les deux exécutent des copies superficielles comme @PasortingckDesjardins dit (malgré les nombreuses âmes induites en erreur qui pensent que CopyTo
fait une copie profonde).
Cependant, CopyTo
vous permet de copier un tableau dans un index spécifié dans le tableau de destination, ce qui lui donne beaucoup plus de flexibilité.
Comme indiqué dans de nombreuses autres réponses, les deux méthodes effectuent des copies superficielles du tableau. Cependant, il existe des différences et des recommandations qui n’ont pas encore été abordées et qui sont mises en évidence dans les listes suivantes.
Caractéristiques de System.Array.Clone
:
CopyTo
car il utilise Object.MemberwiseClone
; Caractéristiques de System.Array.CopyTo
:
Clone
lors de la copie dans un tableau de même type; Array.Copy
héritant des capacités , étant les plus utiles:
int[]
dans un object[]
; object[]
de int
boxed dans un int[]
; int[]
dans un long[]
. Stream[]
dans un MemoryStream[]
(si un élément du tableau source n’est pas convertible en MemoryStream
une exception est générée). Notez également que ces méthodes sont disponibles pour prendre ICloneable
charge ICloneable
et ICollection
. Par conséquent, si vous utilisez des variables de type tableau, vous ne devez pas utiliser Clone
ou CopyTo
, mais utiliser Array.Copy
ou Array.ConstrainedCopy
. La copie contrainte garantit que si l’opération de copie ne peut pas aboutir, l’état du tableau cible n’est pas corrompu.
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"
la source
CopyTo () et Clone () font une copie superficielle. La méthode Clone () crée un clone du tableau d’origine. Il retourne un tableau de longueur exacte.
D’autre part, CopyTo () copie les éléments du tableau d’origine vers le tableau de destination en commençant par l’index de tableau de destination spécifié. Notez que cela ajoute des éléments à un tableau déjà existant.
Le code suivant contredira les écritures indiquant que CopyTo () effectue une copie profonde:
public class Test { public ssortingng 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); }
Laissez-moi vous l’expliquer un peu. Si les éléments du tableau sont de types de référence, la copie (à la fois pour Clone () et CopyTo ()) sera placée au premier niveau (supérieur). Mais le niveau inférieur n’est pas copié. Si nous avons également besoin d’une copie de niveau inférieur, nous devons le faire explicitement. C’est pourquoi, après le clonage ou la copie d’éléments de type référence, chaque élément du tableau Cloné ou Copié fait référence au même emplacement mémoire que celui indiqué par l’élément correspondant du tableau d’origine. Cela indique clairement qu’aucune instance séparée n’est créée pour le niveau inférieur. Et si c’était le cas, changer la valeur d’un élément du tableau Copié ou Cloné n’aurait pas d’effet dans l’élément correspondant du tableau d’origine.
Je pense que mon explication est exhaustive mais je n’ai trouvé aucun autre moyen de le rendre compréhensible.
La méthode Clone()
ne donne pas de référence à l’instance cible pour vous en donner une copie. la méthode CopyTo()
copie les éléments dans une instance existante.
Les deux ne donnent pas la référence de l’instance cible et comme beaucoup de membres disent qu’ils donnent une copie superficielle (copie illusion) sans référence, c’est la clé.
Les réponses sont déroutantes pour moi. Lorsque vous parlez de copie superficielle, cela signifie qu’ils pointent toujours vers la même adresse. Ce qui signifie que changer l’un ou l’autre changera aussi un autre.
Donc, si j’ai A = [1,2,3,4] et que je le clone et que j’obtiens B = [1,2,3,4]. Maintenant, si je change B [0] = 9. Cela signifie que A sera maintenant A = [9,2,3,4]. Est-ce exact?
Les deux sont des copies peu profondes. La méthode CopyTo n’est pas une copie profonde. Vérifiez le code suivant:
public class TestClass1 { public ssortingng 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()
est utilisé pour copier uniquement la structure de données / tableau, il ne copie pas les données réelles.
CopyTo()
copie la structure ainsi que les données réelles.
Remarque: il existe une différence entre Ssortingng [] et SsortingngBuilder [].
In Ssortingng – si vous modifiez la chaîne, les autres tableaux que nous avons copiés (par CopyTo ou Clone) et qui pointent sur la même chaîne ne changeront pas, mais le tableau Ssortingng d’origine pointera sur une nouvelle chaîne, si nous utilisons un SsortingngBuilder dans un tableau, le pointeur Ssortingng ne changera pas, par conséquent, il affectera toutes les copies que nous avons faites pour ce tableau. Par exemple:
public void test() { SsortingngBuilder[] sArrOr = new SsortingngBuilder[1]; sArrOr[0] = new SsortingngBuilder(); sArrOr[0].Append("hello"); SsortingngBuilder[] sArrClone = (SsortingngBuilder[])sArrOr.Clone(); SsortingngBuilder[] sArrCopyTo = new SsortingngBuilder[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 Ssortingng[] 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 }