Différence entre System.Array.CopyTo () et System.Array.Clone ()

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

  • avec Clone() le tableau de destination n’existe pas encore car un nouveau est créé à partir de zéro.
  • Avec 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 :

  • Les tests, utilisant .NET 4.0, montrent qu’il est probablement plus lent que CopyTo car il utilise Object.MemberwiseClone ;
  • Nécessite de convertir le résultat au type approprié;
  • Le tableau résultant a la même longueur que la source.

Caractéristiques de System.Array.CopyTo :

  • Est plus rapide que Clone lors de la copie dans un tableau de même type;
  • Il appelle dans Array.Copy héritant des capacités , étant les plus utiles:
    • Les éléments de type valeur de boîte peuvent être des éléments de type référence, par exemple, en copiant un tableau int[] dans un object[] ;
    • Peut déballer des éléments de type référence dans des éléments de type valeur, par exemple, copier un tableau object[] de int boxed dans un int[] ;
    • Peut effectuer des conversions élargies sur des types de valeur, par exemple, en copiant un int[] dans un long[] .
    • Les éléments peuvent être baissés, par exemple, en copiant un tableau Stream[] dans un MemoryStream[] (si un élément du tableau source n’est pas convertible en MemoryStream une exception est générée).
  • Permet de copier la source vers un tableau cible dont la longueur est supérieure à la source.

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 }