列表克隆后对象参数仍变更的C#技术问题求助
解决列表克隆后对象属性同步变更的问题
嘿,我完全懂你碰到的这个麻烦!这是.NET里非常典型的浅拷贝导致的引用共享问题,咱们来把它捋清楚并解决掉。
问题根源
你用new List<Crêpe>(Ordre)创建的新列表,本质上是做了一次浅拷贝:
- 新列表本身是独立的,所以反转原列表的顺序不会影响克隆列表,这符合你的预期;
- 但列表里的每个
Crêpe元素,其实只是原列表中对应对象的引用——也就是说,两个列表里的同一个“位置”指向的是内存里的同一个Crêpe对象。所以当你修改原列表中对象的FaceCraméBienPlacé属性时,克隆列表里的对应对象自然也会跟着变化,因为它们根本就是同一个东西。
解决方案:实现深拷贝(真正复制每个对象)
要解决这个问题,你需要确保克隆列表时,不仅复制列表本身,还要复制每个Crêpe对象。这里有几种简单可行的方式:
方式1:给Crêpe类添加克隆方法
在你的Crêpe类里新增一个Clone()方法,用来创建当前对象的完全副本:
internal class Crêpe { internal int Nombre { get; set; } internal bool FaceCraméBienPlacé { get; set; } public Crêpe(int position, bool faceCraméBienPlacé) { Nombre = position; FaceCraméBienPlacé = faceCraméBienPlacé; } // 新增克隆方法,返回当前对象的独立副本 public Crêpe Clone() { return new Crêpe(this.Nombre, this.FaceCraméBienPlacé); } }
然后修改你克隆列表的代码,用Select逐个复制对象:
// 代替原来的 new List<Crêpe>(Ordre) Solutions.Add(Ordre.Select(crêpe => crêpe.Clone()).ToList());
方式2:直接在克隆时创建新对象
如果不想给类加方法,也可以在克隆列表的时候直接通过构造函数创建新的Crêpe对象:
Solutions.Add(Ordre.Select(crêpe => new Crêpe(crêpe.Nombre, crêpe.FaceCraméBienPlacé)).ToList());
方式3:实现ICloneable接口(可选)
虽然.NET里ICloneable接口因为返回类型是object有点不便,但也是一种标准实现方式:
internal class Crêpe : ICloneable { internal int Nombre { get; set; } internal bool FaceCraméBienPlacé { get; set; } public Crêpe(int position, bool faceCraméBienPlacé) { Nombre = position; FaceCraméBienPlacé = faceCraméBienPlacé; } public object Clone() { return new Crêpe(this.Nombre, this.FaceCraméBienPlacé); } }
克隆列表时需要做类型转换:
Solutions.Add(Ordre.Select(crêpe => (Crêpe)crêpe.Clone()).ToList());
验证效果
修改之后,你再修改原列表中Crêpe对象的FaceCraméBienPlacé属性时,克隆列表里的对象就不会同步变化了——因为它们现在是内存中完全独立的两个对象,只是初始属性值相同而已。
内容的提问来源于stack exchange,提问作者Zone2Risk
相关产品推荐
相关产品推荐

