多次实例化Game类却共享内存状态的技术问题求助
你遇到的核心问题是**浅拷贝(Shallow Copy)**搞的鬼:你的Game类里的playerCards是引用类型(比如List<string>),而当前的Clone方法只是把原实例的列表引用直接传给了新实例,根本没创建列表的独立副本。这就导致所有通过Clone生成的Game实例,实际上共用同一个playerCards列表——改其中任何一个的列表,其他所有实例都会同步跟着变。
解决方案:实现深拷贝(Deep Copy)
要解决这个问题,你得在Clone方法里对所有引用类型的成员做深拷贝,也就是给它们创建独立的新实例,而不是直接传递原引用。
1. 修改Game的Clone方法
假设playerCards和dealerCards是List<string>类型,修改后的Clone方法要为这些列表创建全新的副本:
public Game Clone() { // 为列表创建独立副本:用原列表的元素初始化新List var clonedPlayerCards = new List<string>(playerCards); var clonedDealerCards = new List<string>(dealerCards); return new Game( clonedPlayerCards, clonedDealerCards, playerHasStood, playerHasSplit, playerHasDoubled ); } // 带参数的Clone重载也一样处理: public static Game Clone(Game game) { var clonedPlayerCards = new List<string>(game.playerCards); var clonedDealerCards = new List<string>(game.dealerCards); return new Game( clonedPlayerCards, clonedDealerCards, game.playerHasStood, game.playerHasSplit, game.playerHasDoubled ); }
2. 检查Shoe类的Clone方法
同理,你的Shoe类里如果有引用类型成员(比如除了int类型的卡片计数外,还有其他自定义对象或列表),也要做同样的深拷贝处理。如果只是int这种值类型,那不用额外操作,但一定要确保所有引用类型成员都被独立复制。
3. 验证效果
修改完成后,每个通过Clone创建的Game实例都会拥有完全独立的playerCards列表。当你调用g.AddPlayerCard(card)时,只会修改当前实例的列表,其他分支里的Game实例状态不会被影响。
额外小提示
如果后续你的类可能添加更多引用类型成员,建议实现ICloneable接口,或者封装一个统一的深拷贝逻辑,避免每次新增成员都要修改Clone方法。另外,也可以用序列化/反序列化的方式实现通用深拷贝(比如用Json.NET序列化后再反序列化),但对于简单的类,手动深拷贝效率会更高。
内容的提问来源于stack exchange,提问作者pingu2k4

