Today a collegue asked for a clean way to clone objects in C#, so that you really have different objects instead of a reference copy . So imagine that you have a class Employee as follows:
1: public class Employee
2: {
3: public string FirstName { get; set; }
4: public string LastName { get; set; }
5: }
and you would copy it:
1: Employee original = new Employee()
2: {
3: FirstName = "Homer",
4: LastName = "Simpson",
5: };
6:
7: Employee copy = original;
8: copy.FirstName = "Marge";
9: Console.WriteLine(string.Format("{0} {1}", original.FirstName, original.LastName));
10: Console.WriteLine(string.Format("{0} {1}", copy.FirstName, copy.LastName));
Changing the first name of the copied object obviously also changes the first name of the original object, because it has been copied by refererence and so original and copy refer to the same object:

And this was not wat we wanted.
To solve it, we first write an extension method that will be available on each class that implements the ICloneable interface:
1: static class Extensions
2: {
3: public static T Clone<T>(this T objectToClone) where T : ICloneable
4: {
5: return (T)objectToClone.Clone();
6: }
7: }
Next we have to make the Employee class implement the ICloneable interface:
1: public class Employee : ICloneable
2: {
3: public string FirstName { get; set; }
4: public string LastName { get; set; }
5:
6: #region ICloneable Members
7:
8: public object Clone()
9: {
10: return new Employee() {FirstName = FirstName, LastName = LastName};
11: }
12:
13: #endregion
14: }
And if we now use the Clone method like:
1: Employee copy = (Employee)original.Clone();
then the new object is really a copy of the original:

If you want to clone a list of objects, add an extension method like this:
1: static class Extensions
2: {
3: public static IList<T> Clone<T>(this IList<T> listToClone) where T : ICloneable
4: {
5: return listToClone.Select(item => (T)item.Clone()).ToList();
6: }
7: }
and to clone this list is then very simple:
1: IList<Employee> copiedList = originalList.Clone();
This example clones only the Employee object (known as shallow copy, see here), but what if the Employee class contains other reference types? In this case we have to implement a deep copy, meaning that every subclass has to implement ICloneable too, for example, if you have a City:
1: public class City: ICloneable
2: {
3: public string CityName { get; set; }
4:
5: #region ICloneable Members
6:
7: public object Clone()
8: {
9: return new City() { CityName = CityName };
10: }
11:
12: #endregion
13: }
then Employee has to clone it like:
1: public class Employee : ICloneable
2: {
3: public string FirstName { get; set; }
4: public string LastName { get; set; }
5: public City City{ get; set; }
6:
7: #region ICloneable Members
8:
9: public object Clone()
10: {
11: return new Employee() {FirstName = FirstName, LastName = LastName, City = (City)City.Clone() };
12: }
13:
14: #endregion
15: }
We can do one other improvement. As you see we always have to cast the Clone operation to its actual type. To solve that we can create a generic ICloneable interface:
1: interface ICloneable<T> : ICloneable
2: {
3: new T Clone();
4: }
and adapt the classes to it:
1: public class Employee : ICloneable<Employee>
2: {
3: public string FirstName { get; set; }
4: public string LastName { get; set; }
5: public City City{ get; set; }
6:
7: #region ICloneable<Employee> Members
8:
9: Employee ICloneable<Employee>.Clone()
10: {
11: return new Employee() { FirstName = FirstName, LastName = LastName, City = City.Clone() };
12: }
13:
14: #endregion
15:
16: #region ICloneable Members
17:
18: object ICloneable.Clone()
19: {
20: return new Employee() { FirstName = FirstName, LastName = LastName, City = City.Clone() };
21: }
22:
23: #endregion
24: }
25:
26: public class City : ICloneable<City>
27: {
28: public string CityName { get; set; }
29:
30: #region ICloneable<City> Members
31:
32: public City Clone()
33: {
34: return new City() { CityName = CityName };
35: }
36:
37: #endregion
38:
39: #region ICloneable Members
40:
41: object ICloneable.Clone()
42: {
43: return new City() { CityName = CityName };
44: }
45:
46: #endregion
47: }