C# - 作为方法参数传递的对象更改状态
C# - Object passed as method parameter changes state
我有一个 class 矩阵,其中包含值的二维数组 public 属性:
public class Matrix
{
public double[,] Values { get; set; }
public Matrix(double[,] values)
{
Values = values;
}
...
}
并且我在 Matrix 中将 *-Operator 作为静态方法重载:
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;
}
而且我在我的 main-class 中做了以下操作:
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);
}
}
运算符本身工作正常,m2 已按预期更改。但是 m1 在乘法后得到与 m2 相同的值。我知道引用类型作为引用传递给方法,但我通过调用 "var resMatrix = new Matrix(m.Values);" 在堆上分配了一个新对象,对吗?或者编译器是否将这两个对象合并为一个对象以进行性能优化?是否有可能像值类型一样保持 m1 相同,如果是这样,这是好的和常见的做法吗?
我怀疑您的 Matrix 构造函数只是存储传入数组的值,而不是对其进行深度复制。在那种情况下,当数组被修改时,它会在两个实例中被修改。
众所周知,Matrix
是引用类型,所以你新建了一个变量:
var resMatrix = new Matrix(m.Values);
但是,double[,]
也是也是引用类型!当您这样做时:
Values = values;
您仍在使 Values
和 values
相互依赖,即改变一个值会影响另一个。
为此,您需要创建一个副本。一种方法是 Clone
:
Values = values.Clone() as double[,];
我有一个 class 矩阵,其中包含值的二维数组 public 属性:
public class Matrix
{
public double[,] Values { get; set; }
public Matrix(double[,] values)
{
Values = values;
}
...
}
并且我在 Matrix 中将 *-Operator 作为静态方法重载:
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;
}
而且我在我的 main-class 中做了以下操作:
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);
}
}
运算符本身工作正常,m2 已按预期更改。但是 m1 在乘法后得到与 m2 相同的值。我知道引用类型作为引用传递给方法,但我通过调用 "var resMatrix = new Matrix(m.Values);" 在堆上分配了一个新对象,对吗?或者编译器是否将这两个对象合并为一个对象以进行性能优化?是否有可能像值类型一样保持 m1 相同,如果是这样,这是好的和常见的做法吗?
我怀疑您的 Matrix 构造函数只是存储传入数组的值,而不是对其进行深度复制。在那种情况下,当数组被修改时,它会在两个实例中被修改。
众所周知,Matrix
是引用类型,所以你新建了一个变量:
var resMatrix = new Matrix(m.Values);
但是,double[,]
也是也是引用类型!当您这样做时:
Values = values;
您仍在使 Values
和 values
相互依赖,即改变一个值会影响另一个。
为此,您需要创建一个副本。一种方法是 Clone
:
Values = values.Clone() as double[,];