在C#中将列表中的所有值复制/克隆到另一个值

时间:2016-01-28 14:02:05

标签: c# list clone

我有一个班级

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并且我没有复制构造器怎么办?

3 个答案:

答案 0 :(得分:4)

你可能会考虑LINQ解决方案:

List<Car> CarsB = (from c in CarsA
                    let a = new Car() { Name = c.Name, Model = c.Model }
                    select a).ToList();

由于NameModel属于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的好处是,如果您有不同类型的结构,界面等,它会将相应的元素复制为新的实例列表。