Reputation: 2275
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
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 notstring
but aclass
, then the operation abovea = 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
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
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