我有一个班级
public class Car()
{
public string Name;
public string Model;
}
我有一个属性
List<Car> CarsA = new List<Car>();
CarsA.Add(new Car(){Name = "Verna",Model="Hyundai"});
CarsA.Add(new Car(){Name = "X1",Model="Bmw"});
我有另一个属性
List<Car> CarsB = new List<Car>();
现在我想将CarsA中的所有条目克隆/复制到CarsB而不将CarsA属性当前实例
(即我想为每个条目创建新对象并添加它)。
像
这样的东西foreach(var car in CarsA)
{
Car newCar =new Car();
newCar.Name = car.Name;
newCar.Model = car.Model;
CarsB.Add(newCar);
}
如果我不想实施ICloneable并且我没有复制构造器怎么办?
答案 0 :(得分:4)
你可能会考虑LINQ解决方案:
List<Car> CarsB = (from c in CarsA
let a = new Car() { Name = c.Name, Model = c.Model }
select a).ToList();
由于Name
和Model
属于string
类型(不可变),因此此操作是安全的。
我觉得这很可读。
相同但使用查询语法:
CarsB = CarsA.Select(c => new Car(){ Name = c.Name, Model = c.Model }).ToList();
注意:假设
Model
不是string
而是class
,那么a = new Car()
以上的操作必须略微改变 它真正克隆了模型中的所有项目(如下所示:Model = c.Model.Clone()
)而不只是引用它(Model = c.Model
)
答案 1 :(得分:3)
如果您要进行深层复制,您的实例序列化为JSON
然后返回是您可以考虑的选项。
然而,这需要比为所有要复制的对象实现复制方法更多的性能。然而,它可以节省大量编写复制方法的时间,即使速度可能要慢百倍,但仍然很快。
我用Json.net使用扩展方法来解决这个问题,如下所示:
public static T Clone<T>(this T source)
{
if (Object.ReferenceEquals(source, null))
return default(T);
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source));
}
这也可以通过其他类型的序列化(不需要第三方库)来完成,正如Scott Chamberlain所指出的那样,例如BinaryFormatter
:(另请注意,当采用这种方法时,你的班级必须是用[Serializable]
属性注释
public static T Clone<T>(this T source)
{
if (Object.ReferenceEquals(source, null))
return default(T);
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, source);
stream.Position = 0;
return (T) formatter.Deserialize(stream);
}
}
然后用法:
foreach(var car in CarsA)
{
CarsB.Add(car.Clone<Car>());
}
它也可以像:
一样使用List<Car> CarsB = CarsA.Clone<List<Car>>();
答案 2 :(得分:1)
Simplified Linq
var CarsB = CarsA.Cast<Car>().ToList();
关于Cast&lt;&gt; ing的好处是,如果您有不同类型的结构,界面等,它会将相应的元素复制为新的实例列表。