深度复制引用类型

时间:2009-10-23 07:26:16

标签: c# .net

我正在使用一个名为BigNumDesc的类来表示数字。我有一个数字的锯齿状数组,代表一个矩阵。 我首先按以下方式声明这个矩阵:

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

现在,我想要调用此方法:

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

我在最后一行有一个断点。如果在观察窗口中,我取任何矩阵项,并更改它,它将改变newMatrix,因为所有BigNumDec都是引用类型(来自它的创建者的糟糕设计决定?)。我怎么能做到这一点?我需要对newMatrix进行修改,所以我必须先从矩阵中复制它。

编辑:现在尝试使用整数,但它发生的情况完全相同。我觉得价值类型不会发生吗?

BigNumDec是不可变的。

3 个答案:

答案 0 :(得分:3)

它仍然在使用值类型的原因是因为您正在使用数组数组。你是浅层复制“外部”数组,它只是将引用复制到两个“内部”数组。

你没有证明BigNumDec是不可变的(我希望如此)但如果是,你应该没问题,如果你只是深度复制数组。或者,您可以使用矩形数组[,]而不是锯齿状数组[][]吗?如果是这样,简单的副本就足够了。对于矩形阵列存在性能影响,请注意 - 值得对此进行测试以确定它是否对您有用。您获得了更好的引用位置,但实际的数组访问速度并不快。

答案 1 :(得分:1)

问题在于你初始化BigNumDec数组,你正在创建一个BigNumDec对象的一维数组。 [0] = {1,2},[1] = {3。4}。然后,您有效地复制引用这些对象,而不是它们的内容,因此值继续改变。

将您的初始化更改为:

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

答案 2 :(得分:1)

如果您的对象是Serializable,则可以使用序列化实现深层复制。它的效率不高(按性能),但很简单。

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

您必须将 BigNumDec 声明为[Serializable]:

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

(正如在其他答案中所述,如果你可以移动到二维数组而不是锯齿状,你会​​得到更好的解决方案)