【发布时间】:2016-07-19 16:17:59
【问题描述】:
我正在使用这个例程将一些坐标加载到容器中,绘制它们,放大它们以及这些任务。然后单击按钮,我倾向于将所有内容重置到原始或初始状态。为此,我会复制一份初始副本并使用该副本。但是在单击重置按钮时,我会销毁副本,获取初始副本的新副本并进行处理。以此类推。
由于某种原因,当我更改副本时,原始容器发生了变化。谁能发现我做错了什么?
按顺序,我先加载数据,然后复制一份:
// CoordPoint is a simple xy point
public List<CoordPoint> MyLoadedCoords { get { return myLoadedCoords; } set { myLoadedCoords = value; }}
public List<CoordPoint> MyDisplayedCoords { get { return myDisplayedCoords; } set { myDisplayedCoords = value }}
private List<CoordPoint> myLoadedCoords;
private List<CoordPoint> myDisplayedCoords;
//..
public void LoadData()
{
// load points from file
MyLoadedCoords = File.ReadLines("C:\\...\\Samples.txt")
// get a copy of original coords
MyDisplayedCoords = MyLoadedCoords.ToList();
}
请注意 MyLoadedCoords 存在 no where 在此处的代码中期望(并且在 Reset 函数中,向下)。然后我处理副本MyDisplayedCoords几个地方类似这样:
public void UpdateDisplayPosition()
{
for (var i = 0; i < MyDisplayedCoords.Count; i++)
{
MyDisplayedCoords[i].X += XCoordOffset; //some processed values
MyDisplayedCoords[i].Y += YCoordOffset; //some processed values
}
}
重置按钮我这样做:
public void ResetZoom()
{
MyDisplayedCoords = MyLoadedCoords.ToList(); // I set break point here
AdjustInitialDisplayPosition();
DrawImage();
}
ResetZoom() 没有达到预期的效果,当我在MyDisplayedCoords = MyLoadedCoords; 上调试和中断时,我看到MyLoadedCoords 包含与MyDisplayedCoords 完全相同的值/对象
编辑:
我在课堂上实现了IClonable 并“覆盖”了Clone() 函数,但它没有工作:
public class CoordPoint : ICloneable
{
// ..
public object Clone()
{
return new CoordPoint {X = X, Y = Y, Z = Z, Color = Color};
}
}
但是,outIClonable,这种“复制”工作就像克隆H.B 回答:
MyDisplayedCoords = MyLoadedCoords.Select(c => new CoordPoint { X = c.X, Y = c.Y, Z = c.Z, Color = c.Color }).ToList();
【问题讨论】:
-
您没有得到副本,您实际上是在处理一个具有所有相同数据指针的新列表。要解决这个问题,您需要使用不支持嵌套引用类型的 Clone,或者实现您自己的深度克隆。
-
@FirstStep, CoordPoint, 是类还是结构?因为如果它是一个类,.ToList() 将创建包含相同引用的新列表。
-
@ArtavazdBalayan 这是一门课。有趣的是我不知道,所以如果它是一个结构,它可以工作吗?
-
@FirstStep,这是一个mini-example。可以看到Lists有不同的hashcode,但是它们的内容是一样的。
-
@ArtavazdBalayan 我明白了。谢谢我今天学到了新东西