2009-10-23 10 views
1

J'utilise une classe appelée BigNumDesc qui représente un nombre. J'ai un tableau déchiqueté de ces nombres, qui représentent une matrice. Je d'abord déclarer cette matrice de la manière suivante:Types de référence de copie profonde

BigNumDec[][] matrix = new BigNumDec[][] { 
     new BigNumDec[] { 1, 2 }, 
     new BigNumDec[] { 3, 4 } 
    }; 

Maintenant, j'ai cette méthode que je veux appeler:

static BigNumDec[][] GetStrictlyUpperTriangle(BigNumDec[][] matrix) 
{ 
    BigNumDec[][] newMatrix = new BigNumDec[matrix.Length][]; 
    matrix.CopyTo(newMatrix, 0); 
    return null; 
} 

J'ai un point de rupture dans la dernière ligne. Si dans la fenêtre de surveillance, je prends n'importe quel élément de matrice, et le change, il changera aussi newMatrix, car tous les BigNumDec sont des types de référence (mauvaise décision de conception de la part de son créateur?). Comment puis-je accomplir cela? J'ai besoin d'apporter des modifications à newMatrix, donc je dois le copier d'abord depuis matrix.

edit: Essayé la même chose maintenant avec ints, mais ça se passe tout de même. Je ne le ferais pas avec des types de valeur?

BigNumDec est immuable.

Répondre

3

La raison pour laquelle cela se produit toujours avec les types de valeur est que vous utilisez un tableau de tableaux. Vous copiez superficiellement le tableau "externe", qui copie simplement les références aux deux tableaux "internes".

Vous n'avez pas montré si BigNumDec est immuable ou non (je l'espère), mais si c'est le cas, ça devrait aller si vous ne faites que copier en profondeur la matrice. Alternativement, pouvez-vous utiliser un tableau rectangulaire [,] au lieu d'un tableau dentelé [][]? Si oui, une simple copie suffirait. Il y a des implications en termes de performances avec les tableaux rectangulaires, cela vaut la peine de tester cela pour voir si cela va poser un problème pour vous. Vous obtenez une meilleure localisation de référence, mais l'accès réel au tableau n'est pas aussi rapide.

+0

Avec un simple pour cela fonctionne bien avec ints. Cela fonctionnera-t-il bien avec BigNumDec? Je dirais non. –

+0

Cela semble fonctionner. Maintenant, je suis confus. –

+0

Pourriez-vous expliquer pourquoi être immuable ou pas fait une différence ici, si possible? Quand il détecte que je veux changer la valeur, en crée-t-il un nouveau dans les coulisses? –

1

Le problème vient de l'initialisation de la baie BigNumDec, vous créez un tableau à une dimension d'objets BigNumDec. [0] = {1, 2}, [1] = {3. 4}. Vous copiez alors efficacement les références de ces objets, pas leur contenu, d'où la raison pour laquelle les valeurs continuent à changer.

Changer votre initialisation à:

BigNumDec[,] matrix = new BigNumDec[,] { 
    { 1, 2 }, 
    { 3, 4 } 
}; 
1

Si vos objets sont Serializable, vous pouvez mettre en œuvre copie en profondeur à l'aide sérialisation. Ce n'est pas très efficace (par performance) mais c'est simple.

public BigNumDec[][] CopyUsingSerialization(BigNumDec[][] original) 
{ 
    var binaryFormatter = new BinaryFormatter(); 
    var serializationStream = new MemoryStream(); 
    binaryFormatter.Serialize(serializationStream, original); 
    serializationStream.Position = 0; 
    var copy = (BigNumDec[][])binaryFormatter.Deserialize(serializationStream); 
    return copy; 
} 

Vous devez déclarer le BigNumDec comme [Serializable]:

[Serializable] 
public class BigNumDec 
{ 
    //class content 
} 

(comme on dit dans d'autres réponses ici, si vous pouvez passer à réseau en deux dimensions au lieu de vous aurez en dents de scie obtenir une meilleure solution)

Questions connexes