C# - 作为方法参数传递的对象改变状态

时间:2017-07-02 16:45:19

标签: c# object reference state method-parameters

我有一个带有2d数组值的类作为公共属性:

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

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

我将* -Operator重载为Matrix中的静态方法:

    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;
    }

我在大班上跟进了:

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相同,如果是这样,它是否是常见的做法?

2 个答案:

答案 0 :(得分:2)

如您所知,Matrix是引用类型,因此您创建了一个新变量:

var resMatrix = new Matrix(m.Values);

但是,double[,] 也是引用类型!当你这样做时:

Values = values;

你仍然使Valuesvalues相互依赖,即改变一个人的价值会影响另一个。

为此,您需要创建副本。一种方法是Clone

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

答案 1 :(得分:0)

我怀疑你的Matrix构造函数只是存储传入的数组的值,而不是制作它的深层副本。在这种情况下,当修改数组时,它将在两个实例中被修改。