1

So I have a list:

List<Class> myList = new List<Class>

I create an object that is equal to one of the items so that I can update it:

Class item = myList[0]

I also have a copy of the item (so that I can restore any changes if needed):

Class copyItem = myList[0]

When I update the item the item in myList also updates, which is what I want.

But I don't want this to happen with the copyItem, how do I make it so that the copy doesn't reference the myList?

DavidSNB
  • 171
  • 1
  • 10
  • 1
    Getting `myList[0]` does not make (or get) a copy of anything. It gets a reference to the same object. –  Jan 30 '20 at 19:33
  • 3
    If you get them *the same way*, why do you expect them to behave differently? – Scott Hunter Jan 30 '20 at 19:34

4 Answers4

5

I think the main issue here is one of expectations:

Class item = myList[0]

does not create an object (assuming that Class is a class, i.e. a reference-type); it makes a copy of the reference and assigns it to the local variable item, but: the reference points to the same, single object.

The key here is that there is only one object; you have only copied the reference, and that's just (essentially) a pointer. It doesn't matter which reference/pointer you use: any change you make still impacts the same object, and you won't have a backup.

For what you need, you'd need to look into creating a clone (deep clone or shallow clone, depending on your needs) of the object.

Alternatively, note that the problems you describe don't apply to value types, but they have much more complex usage constraints that (unless treated very carefully) will trip you up in other subtle ways.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
2

If your Class class (which, by the way, is a terrible name for a class) is simple enough, you can write a copy constructor to help you create a new copy of the instance.

public class Person
{
    public Person() { }
    public Person(Person person) { Name = person.Name; City = person.City; }

    public string Name { get; set; }
    public string City { get; set; }
}

In your main:

var people = new List<Person>
{
    new Person() { Name = "Jane", City = "London" },
    new Person() { Name = "Mike", City = "NY" }
};

var item = people[0];
var copy = new Person(people[0]);

item.City = "LA";

Now;

item.City = "LA"

But

copy.City = "London"

Obviously this approach may not be suitable if your class has a ton of properties or a complex nested structure.

In such a situation you'll need to think about deep/shallow cloning, and this is a good read.

Sach
  • 10,091
  • 8
  • 47
  • 84
0

It doesn't really reference myList, only a member of myList. You will probably need to implement Clone() for Class.

Andrey Belykh
  • 2,578
  • 4
  • 32
  • 46
  • It should be noted that Microsoft recommends against implementing `ICloneable`: https://stackoverflow.com/questions/699210/why-should-i-implement-icloneable-in-c –  Jan 30 '20 at 19:36
0

You can do something like this below so that you can create new object.

Class copyItem = new Class()

Now assign properties from myList[0] like below

copyItem.propery1 = myList[0].property1
copyItem.propery2 = myList[0].property2

Please see Marc Gravell answer for more explanation.

Ziggler
  • 3,361
  • 3
  • 43
  • 61