-1

I am trying to copy a list to another list using AddRange or other ways but nothing seems to work correctly. No matter whatever way I try if, I modify the copied list it modifies the original list too. The only way it work if I copy using foreach loop.

    static void Main(string[] args)
    {
        var test = new List<Employee>{ new Employee { ID = "101", Name ="ABC1"}, new Employee{ID = "102", Name = "ABC2"}, new Employee{ ID = "103", Name = "ABC3"}};

        var tets2 = new List<Employee>(test);

        tets2[0].ID = "1-73";
        TestMethod(test.ToList());
    }

    private static void TestMethod(List<Employee> test)
    {
        var test1 = new List<Employee>(test);

        test1.AddRange(test);

        //This is the only one that work
        foreach(var item in test)
        {
            var x = new Employee { ID = item.ID, Name = item.Name };
            test1.Add(x);
        }

        test1[0].ID = "104";
    }

Is there no shorter way to do it?

Ujjal Das
  • 77
  • 1
  • 7
  • 2
    Possible duplicate of [How do I clone a generic list in C#?](http://stackoverflow.com/questions/222598/how-do-i-clone-a-generic-list-in-c) – nhouser9 Jun 24 '16 at 16:25
  • You could use LINQ for this I believe: `originalList.ForEach(x => CopiedList.Add(new CopiedListObject { prop = x.prop, prop2 = x.prop2 })` – Ingenioushax Jun 24 '16 at 17:06

1 Answers1

3

It's not modifying the list - it's modifying the item in the list. You can have two or more lists - each is a List<Employee> - and if you copy the items to another list or array, the items in both lists are the same items.

var x = new Employee { ID = "xyz", Name = "Bob" };
var list = new List<Employee>();
list.Add(x);
var array = new Employee[]{x};
var y = x;
y.ID = "abc";

In this example there is one and only one instance of Employee, but four references to that one Employee.

  • x is one reference
  • list[0] is another
  • array[0]
  • y

However you refer to that one instance, including list[0].ID = "new id" it's all the same instance of Employee.

To create a copy you could do something like this - this is a verbose example, not necessarily the way you'd want to actually implement it:

var newList = new List<Employee>();
foreach(var employee in sourceList) //the list you want to copy from
{
    newList.Add(new Employee{ID=employee.ID, Name=employee.Name});
}

The items added to newList aren't the same objects in sourceList. They are new objects with the same properties.

If you foresee the need to do this frequently then you could make Employee implement ICloneable.

public class Employee : ICloneable
{
    public string ID {get;set;}
    public string Name {get;set;}
    public object Clone()
    {
        return new Employee{ID=ID, Name=Name};
    }
}

Or, because the properties are just value types, you could just do this, which copies properties from the source object into a new object.

public class Employee : ICloneable
{
    public string ID {get;set;}
    public string Name {get;set;}
    public object Clone()
    {
        return this.MemberwiseClone();
    }
}

Then to create a new list you could create an extension method:

public static class EmployeeExtensions
{
    public static List<Employee> ToClonedList(this IEnumerable<Employee> source)
    {
        return source.Select(employee => employee.Clone() as Employee).ToList();
    }
}

Then you can create a cloned list from any IEnumerable set of employees like this:

var myClonedList = oldList.ToClonedList();

(To split hairs, you don't have to implement ICloneable. You could just write a method that copies the object. ICloneable is just a convention that lets others know they can call .Clone() and create a cloned object.)

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62