Vivek Saurav
Vivek Saurav

Reputation: 2275

Copy/Clone all values from a List to another in a C#

I have a class

public class Car()
{
    public string Name;
    public string Model;
}

And i have a property

List<Car> CarsA = new List<Car>();
CarsA.Add(new Car(){Name = "Verna",Model="Hyundai"});
CarsA.Add(new Car(){Name = "X1",Model="Bmw"});

and i have another property

List<Car> CarsB = new List<Car>();

Now i want to add clone/copy all the entries from CarsA to CarsB without taking CarsA properties current instances

(i.e. i want to create new object for each entry and add it).

Something like

foreach(var car in CarsA)
{
    Car newCar =new Car();
    newCar.Name = car.Name;
    newCar.Model = car.Model;
    CarsB.Add(newCar);
}

What if i don't want to implement ICloneable and i don't have a copy contructor?

Upvotes: 6

Views: 9206

Answers (3)

Ian
Ian

Reputation: 30813

You could probably consider LINQ solution:

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

Since Name and Model are of string type (which is immutable), this operation is safe.

It is quite readable, I think.

Same but with query syntax:

CarsB = CarsA.Select(c => new Car(){ Name = c.Name, Model = c.Model }).ToList();

Note: If, suppose, the Model is not string but a class, then the operation above a = new Car() must be slightly change to something which really clone all the items in the model (something like this: Model = c.Model.Clone()) and not just referring to it (Model = c.Model)

Upvotes: 6

Simon Karlsson
Simon Karlsson

Reputation: 4129

If you want to do a deep copy your instances serializing to JSON and then back is an option you could consider.

This however will require a lot more performance than implementing copy methods for all objects to be copied. However it saves a lot of time writing copy methods, and even though it might be hundred's of times slower it's still fast.

I use to solve this with Json.net using an extension method looking something like this:

public static T Clone<T>(this T source)
{
    if (Object.ReferenceEquals(source, null))
        return default(T);

    return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source));
}

This can also be done with other types of serialization(that does not require 3rd party libs) as pointed out by Scott Chamberlain, example with BinaryFormatter: (Also note when going with this approach your class has to be annotated with the [Serializable] attribute)

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);
    }
}

Usage would then be:

foreach(var car in CarsA)
{
    CarsB.Add(car.Clone<Car>());
}

It could also be used like:

List<Car> CarsB = CarsA.Clone<List<Car>>();

Upvotes: 3

DRapp
DRapp

Reputation: 48139

Simplified Linq

var CarsB = CarsA.Cast<Car>().ToList();

The nice thing about the Cast<>ing is that if you have different types that have similar structure, interface, etc, it will copy the respective elements as the new instanced list.

Upvotes: 1

Related Questions