web-dev-qa-db-fra.com

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

Quelle est la différence entre la System.Array.CopyTo() et System.Array.Clone()?

72
Mister Dev

La méthode Clone () renvoie un nouvel objet tableau (une 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 effectuent une copie superficielle. Une copie superficielle signifie que le contenu (chaque élément du tableau) contient des références au même objet que les éléments du tableau d'origine. Une copie complète (qu'aucune de ces méthodes n'effectue) créerait une nouvelle instance de l'objet de chaque élément, résultant en un objet différent, mais identique.

La différence est donc:

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.

Supprimez le mauvais exemple.

47
Patrick Desjardins

Une autre différence non mentionnée jusqu'à présent est que

  • avec Clone() le tableau de destination n'a pas encore besoin d'exister puisqu'un nouveau est créé à partir de zéro.
  • avec CopyTo() non seulement le tableau de destination doit déjà exister, il doit être suffisamment grand pour contenir tous les éléments du tableau source à partir de l'index que vous spécifiez comme destination.
25
Michael Burr

Les deux effectuent des copies superficielles comme l'a dit @PatrickDesjardins (malgré les nombreuses âmes trompées qui pensent que CopyTo fait une copie complète).

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é.

21
FlySwat

Comme indiqué dans de nombreuses autres réponses, les deux méthodes exécutent copies superficielles du tableau. Cependant, il existe des différences et des recommandations qui n'ont pas encore été traité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 plus lent que CopyTo probablement parce qu'il utilise Object.MemberwiseClone ;
  • Nécessite de lancer le résultat dans le 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 vers un tableau du même type;
  • Il appelle Array.Copy héritant sont les capacités , étant les plus utiles:
    • Peut encadrer des éléments de type valeur dans des éléments de type référence, par exemple, copier un int[] tableau dans un object[];
    • Peut décompresser des éléments de type référence dans des éléments de type valeur, par exemple, en copiant un object[] tableau de int encadré dans un int[];
    • Peut effectuer des conversions élargies sur les types de valeur, par exemple, en copiant un int[] dans une long[].
    • Peut abattre des éléments, par exemple, copier un Stream[] tableau dans un MemoryStream[] (si un élément du tableau source n'est pas convertible en MemoryStream une exception est levée).
  • Permet de copier la source dans un tableau cible qui a une longueur supérieure à la source.

Notez également que ces méthodes sont disponibles pour prendre en charge ICloneable et ICollection , donc si vous avez affaire à des variables de types de tableau, vous devez n'utilisez pas Clone ou CopyTo et utilisez plutôt Array.Copy ou Array.ConstrainedCopy . La copie contrainte garantit que si l'opération de copie ne peut pas aboutir, l'état de la baie cible n'est pas corrompu.

18
João Angelo
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

7
GenZiy

CopyTo () et Clone () font une copie superficielle. La méthode Clone () crée un clone du tableau d'origine. Il renvoie un tableau de longueur exacte.

D'un autre côté, CopyTo () copie les éléments du tableau d'origine vers le tableau de destination à partir de 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 articles disant que CopyTo () fait une copie complète:

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);
}

Permettez-moi de l'expliquer un peu. Si les éléments du tableau sont de type référence, la copie (à la fois pour Clone () et CopyTo ()) sera effectuée jusqu'au premier niveau (supérieur). Mais le niveau inférieur n'est pas copié. Si nous avons également besoin d'une copie du 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é se réfère au même emplacement mémoire que celui référencé par l'élément correspondant dans le tableau d'origine. Cela indique clairement qu'aucune instance distincte n'est créée pour le niveau inférieur. Et s'il en était ainsi, la modification de la valeur d'un élément du tableau copié ou cloné n'aurait aucun effet sur l'élément correspondant du tableau d'origine.

Je pense que mon explication est exhaustive mais je n'ai trouvé aucun autre moyen de la rendre compréhensible.

2
Prasad

Array.Clone ne nécessite pas de tableau cible/destination pour être disponible lors de l'appel de la fonction, tandis que Array.CopyTo nécessite un tableau de destination et un index.

0
Aikansh Mann

La méthode Clone() ne fait pas référence à l'instance cible, vous en donne juste 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 de nombreux membres disent qu'ils donnent une copie superficielle (copie illusion) sans référence, c'est la clé.

0
Mohammad Ahmed

Les deux sont des copies superficielles. La méthode CopyTo n'est pas une copie complète. Vérifiez le code suivant:

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 */
0
Nikhil Redij

Les réponses me déroutent. Lorsque vous dites copie superficielle, cela signifie qu'ils pointent toujours vers la même adresse. Ce qui signifie que changer l'un ou l'autre en changera également un autre.

Donc, si j'ai A = [1,2,3,4] et je le clone et 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?

0
Stranger