2

I'm working on quite a complex project and have been struggling to debug one problem for the last hour. I nailed down the troublesome code which looks more or less like this:

Client ClientToChange = Clients[index];
ClientToChange.Rank = 80;

Clients is a static array of classes Client, declared in the same class.

Changing ClientToChange's rank for some reason alters the contents of the array, i.e.

Console.WriteLine(Clients[index].Rank)

returns 80 (whereas before it was 100), of course index was not changed.

This seems bizarre to me, but that's what happens.

I wrote a little dummy program to test this out, just to make sure:

    static string[] foo = new string[10];
    static void Main(string[] args)
    {

        foo[3] = "bar";

        string test = "";
        test = foo[3];

        test = "fb";

        Console.Write(foo[3]);
        Console.Write(test);

This, of course, works like it should: prints barfb.

Am I doing something that I cannot see, or I don't know something I should?

rene
  • 41,474
  • 78
  • 114
  • 152
user4520
  • 3,401
  • 1
  • 27
  • 50
  • 2
    Not so much modifying a copy, as modifying the element and accessing it through a second reference to the same element. – ClickRick May 10 '14 at 16:39

1 Answers1

5

When you do the assignment

Client ClientToChange = Clients[index];

You are making ClientToChange a reference to the object at Clients[index], not copying it. They are both names that happen to point to the same object. It makes sense that when you change it, you see those changes, whichever name you use (a reference in an array is just a particular type of name).

If you want a different object, you should copy it.

The reason your string case doesn't show this behaviour is because in that case, you are not modifying the contained string, but rather changing the name to point to another object. Changing what one name points to doesn't change what the other names point to. If you were to mutate the string (which you can't do, as C# strings are immutable), then you would see the change when accessing it through the array.

Community
  • 1
  • 1
Gareth Latty
  • 86,389
  • 17
  • 178
  • 183
  • 1
    "The reason your string case doesn't show this behaviour is because in that case, you are not modifying the contained string, but rather changing the name to point to another object." - and this happens because strings are immutable in C#, is that correct? – user4520 May 10 '14 at 16:47
  • 2
    @szczurcio No, any time you do an assignment (=) you are changing what that name is pointing to, not changing the item being pointed to. It's only if you perform operations on that item itself (changing attributes or calling methods that do so) that cause mutation, and therefore change the value. So it's not because it's immutable, rather, it's only possible to change a mutable value, so you can't see the behaviour you had before with a mutable value. – Gareth Latty May 10 '14 at 16:50
  • 1
    OK, I understand now. I can't believe I survived so long without understanding this behavior though. Thank you. – user4520 May 10 '14 at 16:54