首先,很抱歉无法提出更好的标题。不过我试过了。
我有这样的课
public class GameBoard : ICloneable {
private bool _isCloned;
public ObservableCollection<BoardPosition> BoardPositions { get; set; }
public GameBoard() {
BoardPositions = new ObservableCollection<BoardPosition>();
//this.BoardPositions.CollectionChanged += BoardPositionsOnCollectionChanged;
}
private void BoardPositionsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) {
// if this event is raised from the NEW object, [this] still points to the OLD object
}
public object Clone() {
//var gameBoard = (GameBoard)this.MemberwiseClone();
var gameBoard = new GameBoard {
// make it VERY clear this is just a clone
_isCloned = true,
// deep copy the list of BoardPositions
BoardPositions =
new ObservableCollection<BoardPosition>(this.BoardPositions.Select(p => p.Clone()).Cast<BoardPosition>())
};
gameBoard.BoardPositions.CollectionChanged += BoardPositionsOnCollectionChanged;
// why does the target of the event point to the old object?!?
return gameBoard;
}
}
public class BoardPosition : ICloneable {
public int[] Coordinates { get; set; }
public BoardPosition(int[] coordinates) {
Coordinates = coordinates;
}
public object Clone() {
return new BoardPosition(new int[]{this.Coordinates[0], this.Coordinates[1], this.Coordinates[2]});
}
}
它实现了 ICloneable。在 Clone 方法中,我深度复制 ObservableCollection,并附加 CollectionChanged 事件处理程序。
现在的问题是,当新的克隆对象的 CollectionChanged 事件触发时,[this] 指向被克隆的旧对象。这可以很容易地观察到,因为在引发事件时 _isCLoned 始终为 false,即使在克隆期间它被设置为 true。为什么会这样,我该怎么办?我当然希望 [this] 引用新的克隆对象。
var gameBoard = new GameBoard();
gameBoard.BoardPositions.Add(new BoardPosition(new[] {1, 2, 3}));
var clonedBoard = (GameBoard)gameBoard.Clone();
clonedBoard.BoardPositions.Add(new BoardPosition(new[] { 2, 3, 4 }));