如何在没有引用的情况下正确克隆多维数组
本文关键字:数组 情况下 引用 | 更新日期: 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();
}
}