0

I am not sure where is the problem with the code below where value of one class instance change the value of another. It seems that I have problem property of type class where the value set in one class affects the value of another class of the same type. Example is below. What I want to achieve is after the assignment of value from one class (Result 2) , the subsequent manipulation of the the other class does not effect the previous one.

public class Address {
    public string Street {
        get;
        set;
    }
}

public class Person {
    public string Name { 
        get; 
        set; 
    }

    public List<Address> Addresses { 
        get; 
        set; 
    } = new List<Address>();

    public int Age { 
        get; 
        set; 
    }
}

public class Employee {
    public string EmpID {
        get;
        set;
    }

    public Person EmployeePerson {
        get;
        set; 
    }
}

var emp = new Employee { 
    EmpID = "1", 
    EmployeePerson = new Person { 
        Name = "Alice", Addresses = 
        new List<Address> { 
            new Address { 
                Street = "123 Street" 
            }
        } 
    } 
};

var per = new Person { 
    Name = emp.EmployeePerson.Name, Addresses = emp.EmployeePerson.Addresses };

per.Addresses[0].Street = "New Street";
per.Name = "New Name";   

Console.WriteLine("Result 1: {0} , {1}", 
    emp.EmployeePerson.Name, per.Name);
    
Console.WriteLine("Result 2: {0} , {1}", 
    emp.EmployeePerson.Addresses[0].Street, per.Addresses[0].Street);

Result 1: Alice , New Name

Result 2: New Street , New Street

IndieGameDev
  • 2,905
  • 3
  • 16
  • 29
AlbertK
  • 429
  • 2
  • 8
  • 21
  • `Result 1: Alice , New Name Result 2: New Street , New Street` What _exact_ output did you expect? – mjwills Oct 08 '20 at 06:09
  • The link you have provide seems to be best way to resolve the issue without adding new custom codes. – AlbertK Oct 08 '20 at 09:31

1 Answers1

3

List<T> is a reference type. In your example, emp.EmployeePerson and per have both a reference to the same list. If you manipulate the list, you will see the changes in both variables.

You can avoid this by creating a new list when you initialise the per variable by copying the old list. But Address is also a reference types, so both lists will hold references to the same instance. You also have to copy your address variables. I added a Copy() method to your Address class:

var per = new Person { Name = emp.EmployeePerson.Name, Addresses = emp.EmployeePerson.Addresses.Select<Address,Address>(x => x.Copy()).ToList() };

public class Address
{
    public string Street {get;set;}
        
    public Address Copy()
    {
        return new Address { Street = this.Street };
    }
}

The distinction between reference types and value types is quite fundamental in C#. Here is some information from the official documentation:

https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/reference-types https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/value-types

SomeBody
  • 7,515
  • 2
  • 17
  • 33
  • How do I assign the Addresses without transforming it to a List – AlbertK Oct 08 '20 at 05:49
  • I am sorry, I thought Address is a list of strings. Because it is a list of your `Address` class, it makes it a bit more complicated. You'll have to copy the list and the instances of your `Address` class – SomeBody Oct 08 '20 at 06:00
  • 1
    Make addresses readonly like so: `public List
    Addresses { get; } = new List
    ();` (i.e. remove the setter). Then do not assign to addresses, but add new addresses: `Addresses.Add(new Address {...})`.
    – heijp06 Oct 08 '20 at 06:03
  • Is there a better way around this?. I mean to convert the reference type to value type. – AlbertK Oct 08 '20 at 06:20
  • `List` is always a reference type. If you want `Address` also being a value type, change it from `class` to `struct`. But before you go on, I recommend you to do a lot of reading, because if you don't understand how to deal with reference and value types, you will be lost quite soon. – SomeBody Oct 08 '20 at 06:22