Comment faire une copie profonde d'un tableau?
Je passe un tableau à deux dimensions en tant que bien à mon contrôle de l'utilisateur. J'y stocker ces valeurs dans un autre tableau à deux dimensions:
int[,] originalValues = this.Metrics;
Plus tard, j'ai changer les valeurs dans this.Metrics
. Mais maintenant, si je récupérer les valeurs d'une originalValues, j'ai changé les valeurs de this.Metrics
. Comment puis-je faire une copie et de ne pas copier les références en C#?
source d'informationauteur
Vous devez vous connecter pour publier un commentaire.
Vous pouvez cloner un tableau, qui fait une copie de celui-ci:
Je ne sais pas où j'ai obtenu ce à partir, mais cela fonctionne bien pour moi.
Si l'objet que vous avez copié est un tableau, alors vous pouvez utiliser:
Cela vous donnera une copie du tableau original dans votre tableau de destination.
Le noeud du problème est là:
C'est en fait inexact. Vous n'êtes pas de la création d'un nouveau tableau; vous définissez votre
originalValues
variable la même tableau. Pour une explication plus détaillée, voir ci-dessous.La confusion exprimée dans les commentaires de Pieter de réponse est en raison de l'incertitude entourant le terme "copie en profondeur."
Quand il s'agit de la copie d'objets, il y a copie profonde et peu profonde de la copie.
Profonde de la copie s'agit de faire une copie de tous les données appartenant à un objet, ce qui signifie que si l'objet est composé de membres qui sont eux-mêmes complexes (par exemple, les instances de l'utilisateur défini les types de référence), ces objets doit être profonde copié (avec tous leur membres, et ainsi de suite).
Peu profonde de la copie suppose simplement la copie de tous les champs d'un objet à l'autre, ce qui signifie que si l'objet comprend les types de référence, seules les références doivent être copiés (et donc le copié les références pointant vers le même objet).
Dans le cas du code que vous avez posté:
... il y a en fait aucune copie de tous les objets à tous les. Tout ce que vous avez fait est copié une référence unique, de l'affectation de la valeur de
this.Metrics
(une référence) à la variableoriginalValues
(également une référence, au même tableau). C'est essentiellement la même qu'une simple affectation de la valeur, comme ceci:Maintenant, le
Array.Clone
méthode permet, en fait, un peu profonde copie. Mais comme Pieter souligné, il n'y a vraiment pas de différence entre un "peu profonde" ou "profond" copie d'un tableau de entierspuisque les nombres entiers ne sont pas des objets complexes.Si vous aviez quelque chose comme ceci:
..., vous finirais avec une toute nouvelle tableau (une copie, oui), mais qui contient tout de même
StringBuilder
objets (donc d'une copie). C'est là une profonde peu profonde contre la copie; si vous vouliez un nouveau tableau contenant copies de tous lesStringBuilder
objets debuilders
vous auriez besoin de faire une copie en profondeur.Vous pouvez propriétédeepcopy 1d tableau à l'aide de LINQ.
Avec un tableau 2d, cela ne fonctionnera pas parce que 2d matrice de ne pas mettre en œuvre IEnumerable.
IClonable est grande, mais à moins que vous
IClonable
chaque type dans votre top niveau cloné type, vous vous retrouvez avec des références, autant que je sache.Sur cette base, sauf si vous voulez marcher l'objet et le clone de chaque objet à l'intérieur, ce qui semble l'approche la plus simple.
C'est simple et garantit une rupture nette avec les références de la profondeur des objets dans l'original:
Utilisation:
Où
ComplexType
est quelque chose qui veulent une pause de références.Il faut de tout Type, stringifies, puis de stringifies à une nouvelle copie.
Meilleur exemple d'utilisation:
Si vous avez sélectionné un type complexe comme un résultat d'un lambda de requête et souhaitez modifier le résultat, sans affecter l'original.
Vous avez besoin pour créer un nouveau tableau. Ensuite, vous devez copier manuellement le valeur de chaque élément dans le tableau. Ce que vous faites dans l'exemple donné est de créer deux variables de tableau qui, à la fois référence à la même matrice.
Le problème avec la méthode clone est que c'est une copie superficielle. Dans ce isntance, parce que vous êtes à l'aide de
int
il n'a pas de mater. Howver, si vous aviez un tableau de classes de la définition de la ICLonable interface laisse ambiguë quant à la façon dont profondément le clone va aller.Imaginez si vous aviez une classe qui a des propriétés qui sont les autres classes qui a des propriétés qui sont les autres classes. Le clonable interface ne précise pas si il sera également clone de la sous-membres ou non. En outre, beaucoup de gens ont des opinions différentes sur ce que le comportement attendu est.
C'est donc pourquoi il est souvent recommandé de définir deux interfaces,
IShallowCopy
etIDeepCopy
.Si vous voulez profonde copie d'un tableau de types de référence, vous pouvez le faire de cette méthodologie:
Mettre en œuvre
IClonable
iterface pour votre classe et de faire de votre copie en profondeur de toute valeur saisie des champs à l'intérieur d'un autre objet construit.Ensuite, vous pouvez faire la copie réelle à l'aide de