如何在没有引用的情况下正确克隆多维数组

本文关键字:数组 情况下 引用 | 更新日期: 2023-09-27 18:32:32

我的程序中有三维数组。我想调试其中的值,并将此数组放入另一个数组中,我想在其中找到差异。

我试过这个:

Weights weights = new Weights(); // init inside
List<Weights> weightsDebug = new List<Weigts>();
weightsDebug.Add(weights); // I'd put first weigths into the list 
for(int i = 0; i < 100; i++) {
    // do some bad things with weights;
    weightsDebug.Add(weights);
}

在那之后,我在weigthsDebug的所有99个元素中都得到了相同的权重值。我尝试调试,我意识到,weigts 数组正在更改。我知道问题出在引用中(按链接复制,而不是按值复制)——所有推送到weightsDebug数组元素都与主循环中的weights链接。

我用谷歌搜索了一下,发现了一些复制一维数组的方法。我接下来试过:

我将克隆方法添加到我的权重类中:

double[][][] values;
public Weights Clone() {
    Weights clone = new Weights();
    clone.values = (double[][][]) this.values.Clone();
    return clone;
}
public Weights()
{
    Console.WriteLine("Constructor WITHOUT arguments fired");
}

现在我在复制权重时这样做:

Weights weights = new Weights(); // init inside
List<Weights> weightsDebug = new List<Weigts>();
weightsDebug.Add(weights); // I'd put first weigths into the list 
for(int i = 0; i < 100; i++) {
    // do some bad things with weights;
    Weights weightsClone = weights.Clone();
    weightsDebug.Add(weightsClone);
}

而且我仍然在整个调试数组中获取最后更改的值。我该如何纠正它?

如何在没有引用的情况下正确克隆多维数组

您在这里真正要寻找的是深度克隆,而不是您正在实现的当前浅层克隆。

很久以前,我们意识到,通过使类可序列化,我们可以使用 .Net 序列化类快速、轻松、正确地制作任何对象的深层克隆。

以下是我们用于深度克隆的方法(还有一个使用 DataContractSerializer 的 SilverLight 变体):

    /// <summary>
    /// This method clones all of the items and serializable properties of the current collection by 
    /// serializing the current object to memory, then deserializing it as a new object. This will 
    /// ensure that all references are cleaned up.
    /// </summary>
    /// <returns></returns>
    /// <remarks></remarks>
    public T CreateSerializedCopy<T>(T oRecordToCopy)
    {
        // Exceptions are handled by the caller
        if (oRecordToCopy == null)
        {
            return default(T);
        }
        if (!oRecordToCopy.GetType().IsSerializable)
        {
            throw new ArgumentException(oRecordToCopy.GetType().ToString() + " is not serializable");
        }
        var oFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        using (var oStream = new MemoryStream())
        {
            oFormatter.Serialize(oStream, oRecordToCopy);
            oStream.Position = 0;
            return (T)oFormatter.Deserialize(oStream);
        }
    }

若要使用它,请首先确保 Weights 类使用 Serializable 属性进行标记:

[Serializable]
public class Weights

然后,您可以根据需要进行克隆:

        var weights = new List<Weights>();
        weights.Add(new Weights());
        var debugWeights = CreateSerializedCopy<List<Weights>>(weights);
        if (debugWeights[0] == weights[0])
        {
            System.Diagnostics.Debug.WriteLine("Did not serialize correctly");
        }

这里的问题是你没有一个真正的多维数组,只有一个对象。你有一个"交错"的多维数组,其中的对象实际上是数组数组的数组。这意味着要克隆对象,您需要做更多的工作:

clone.values = new double[values.Length][][];
for (int i = 0; i < values.Length; i++)
{
    clone.values[i] = new double[values[i].Length][];
    for (int j = 0; j < values[i].Length; j++)
    {
        clone.values[i][j] = (double[])values[i][j].Clone();
    }
}
相关文章: