To understand the behavior of class-types, including strings, regard all class-type parameters, variables, fields, and array elements, etc. as holding "object ids". If Foo
is a variable of type string
, the statement Foo = 12345.ToString();
will create a new object id (hypothetically, Object ID#197), and create a new object of type string
with that id, holding the five characters "12345"
. It will then store Object ID#197
into the variable Foo
. If one calls a routine with a non-ref parameter param
, and passes Foo
to it, then param
will be a local variable holding Object ID #197
. The statement param += "6";
would create a new object (e.g. Object ID #521), of type string, holding the six characters "123456"
and store Object ID #521
into param
. Note that Foo
still holds Object ID#197
, and that object still holds the five-character string "12345"
.
If param
had been passed by ref
, then the statement param += "6"
would have stored Object ID #521
into Foo
. It still would not have caused any observable change to Object #197, except perhaps to make it eligible for garbage collection (if Foo
had been the only reference to Object #197, overwriting it would mean that there would no longer exist any reference to that object anywhere in the universe).
Note that it's generally pretty easy to reason about immutable class types like string
, even without thinking in terms of Object IDs, since the only way to change the sequence of characters represented by a string variable is to store a different Object ID there. Thinking in terms of Object IDs becomes essential, however, when dealing with mutable class types. Passing a variable of class type Car
, not by ref, would be equivalent to copying a VIN from one slip of paper to another, and handing the latter slip of paper to some shop workers, and asking them to do something with it. If the first paper originally identified a red car with VIN#15934, then when the workers were done the first paper might identify a blue car with VIN#15934, but it would be the same car. Nothing the workers could do with the slip of paper they were given, nor anything they could do with the car, would change which car the first paper referred to. On the other hand, passing the parameter by reference would be more like the shop workers a piece of paper with the VIN written on it, and getting the paper back from them when they were done. If the workers could cross out the VIN and write another, then when they returned the slip of paper it might refer to the same car or a different car; if it refers to a different car, the car to which it originally referred may or may not have been modified, and the car to which the paper ends up referring may or may not bear any resemblance to the original.