Quelle est la différence entre la System.Array.CopyTo()
et System.Array.Clone()
?
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.
Une autre différence non mentionnée jusqu'à présent est que
Clone()
le tableau de destination n'a pas encore besoin d'exister puisqu'un nouveau est créé à partir de zéro.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.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é.
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
:
CopyTo
probablement parce qu'il utilise Object.MemberwiseClone
;Caractéristiques de System.Array.CopyTo
:
Clone
lors de la copie vers un tableau du même type;Array.Copy
héritant sont les capacités , étant les plus utiles: int[]
tableau dans un object[]
;object[]
tableau de int
encadré dans un int[]
;int[]
dans une long[]
.Stream[]
tableau dans un MemoryStream[]
(si un élément du tableau source n'est pas convertible en MemoryStream
une exception est levée).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.
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"
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.
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.
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é.
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 */
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?