C# 给CardLib添加深度复制
使用ICloneable接口,复制Caixl、Cards和Deck对象,这在某些扑克牌游戏中是有用的,因为在这些游戏中不需要让两副扑克牌引用同—组Caid对象,但肯定会使一副扑克牌中的牌序与另一副牌的牌序相同。
在ChllCardLib中,对Can!类执行复制操作是很简单的,因为只需要进行浅度复制(Card只包含值类型的数据,其形式为字段)。我们只需要对类定义进行如下修改:
public class Card : ICloneable
{
public object Clone() => MemberwiseClone();
ICloneable接口的这段实现代码只是一个浅度复制,无法确定在Clone()方法中执行了什么操作,但这己经足以满足我们的需要。
接着,需要对Cards集合类实现ICloneable接口。这个过程稍复杂些,因为涉及到复制源集合中的每个Gmi对象,所以需要进行深度复制:
public class Cards : CollectionBase, ICloneable
{
public object Clone()
{
Cards newCards = new Cards();
foreach (Card sourceCard in List)
{
newCards.Add((Card)sourceCard.Clone());
}
return newCards;
}
最后,需要在Deck类上实现ICloneable接口。这里存在一个小问题:因为Chi ICardLib中的Deck类无法修改它包含的扑克牌,所以没有洗牌。例如,无法修改有给定牌序的Deck实例。为解决这个问题,为Deck类定义一个新的私有构造函数,在实例化Deck对象时,可以给该函数传递一个特定的Cards集合。所以,在这个类中执行复制的代码如下所示:
public class Deck : ICloneable
{
public object Clone()
{
Deck newDeck = new Deck(cards.Clone() as Cards);
return newDeck;
}
private Deck(Cards newCards) => cards = newCards;
再次用一些简单的客户代码进行测试。与以前一样,这些代码应放在客户项目的MainO方法中,以便进行测试:
Deck deckl = new Deck();
Deck deck2 = (Deck)deckl.Clone();
WriteLine($"The first card in the original deck is: {deckl.GetCard(0)}");
WriteLine($"The first card in the cloned deck is: {deck2.GetCard{0)}");
deckl.Shuffle();
WriteLine ("Original deck shuffled.");
WriteLine($"The first card in the original deck is: {deckl.GetCard(0)}");
WriteLine($"The first card in the cloned deck is: {deck2.GetCard(0)}");
ReadKey();
其输出结果如图所示。
点击加载更多评论>>