2017-07-02 1 views
0

J'ai une matrice de classe avec un 2d-tableau de valeurs comme une propriété publique:C# - objet passé en tant que paramètre de méthode change d'état

public class Matrix 
{ 
    public double[,] Values { get; set; } 

    public Matrix(double[,] values) 
    { 
     Values = values; 
    } 
    ... 
} 

Et je surchargé le * -operator comme méthode statique à l'intérieur de la matrice :

public static Matrix operator *(Matrix m, double operand) 
    { 
     var resMatrix = new Matrix(m.Values); 
     for (var i = 0; i < resMatrix.Values.GetLength(0); i++) 
     { 
      for (var j = 0; j < resMatrix.Values.GetLength(1); j++) 
      { 
       resMatrix[i, j] *= operand; 
      } 
     } 
     return resMatrix; 
    } 

Et je ne suit dans ma classe principale:

internal class Program 
{ 
    public static void Main(string[] args) 
    { 
     var m1 = new Matrix(new double[,] 
     { 
      {1, 2, 3}, 
      {4, 5, 6}, 
      {7, 8, 9} 
     }); 
     Console.WriteLine(m1); 

     var m2 = m1 * 2; 

     Console.WriteLine(m2); 
     Console.WriteLine(m1); 
    } 
} 

L'opérateur lui-même fonctionne très bien, m2 est modifiée comme i ntended. Mais m1 obtient les mêmes valeurs que m2 après la multiplication. Je sais que les types de références sont passés comme référence dans une méthode, mais j'ai alloué un nouvel objet sur le tas avec l'appel "var resMatrix = new Matrix (m.Values);" droite? Ou le compilateur fusionne-t-il ces deux objets en un pour l'optimisation des performances? Y a-t-il une possibilité de garder m1 comme les types de valeur, et si oui, est-ce une bonne pratique courante?

Répondre

2

Comme vous le savez, Matrix est un type de référence, de sorte que vous avez fait une nouvelle variable:

var resMatrix = new Matrix(m.Values); 

Cependant, double[,] est également un type de référence! Lorsque vous faites ceci:

Values = values; 

Vous faites toujours Values et values dépendants les uns des autres à savoir changer sa valeur aura une incidence sur l'autre.

Pour ce faire, vous devez créer une copie. Une façon de le faire est Clone:

Values = values.Clone() as double[,]; 
0

Je soupçonne que votre constructeur Matrix stocke simplement la valeur du tableau passé plutôt que d'en faire une copie complète. Dans ce cas, lorsque le tableau est modifié, il sera modifié dans les deux cas.

+0

oui, c'est exact, je vais ajouter mon constructeur dans l'exemple de code dans ma question. Avez-vous des suggestions sur la façon de créer une copie en profondeur? Et pourquoi cela doit-il arriver dans le constructeur? –