Re: System.String: It doesn't seem to act like a reference type.

Tech-Archive recommends: Fix windows errors by optimizing your registry

From: Bruce Wood (brucewood_at_canada.com)
Date: 01/25/05


Date: 24 Jan 2005 16:01:38 -0800

A couple of problems here.

First, because Strings are immutable, changing the value of a string
doesn't really change the string _in situ_ in memory. Instead, it
creates a whole new string and points the String reference to it.

When you say:

String a = "Old Value";
a = "New Value";

you haven't really changed what is at the memory location where the
string "Old Value" lives. It's still there, if only for a short time
before the garbage collector comes around to sweep it up. What has
happened is that a whole new object in memory, a String instance, has
been created with the value "New Value". The variable a, which contains
a pointer (or a _reference_) to a string, is then changed to refer to
the new String instance (with the value "New Value") instead of the old
one (with the value "Old Value").

Now let's look at what happens when two String variables are involved:

String a = "Old Value";
String b = a;
a = "New Value";

After the first line executes, there is a new String instance in the
heap with the value "Old Value", and the variable "a" contains a
reference to the memory location on the heap where that String instance
is stored.

The second line just copies the reference to the String instance with
the value "Old Value" from "a" to "b". Now both String variables have
the same value, but be careful what I mean by "value": their value is
_not_ a String "Old Value". Their value is a _reference_ or a pointer
to a memory location at which is found a String with the value "Old
Value".

The third line instantiates a new String instance in the heap and gives
it the value "New Value". It then changes the String variable "a" to
contain a reference to this new String instance. Notice that nothing
has happened to the variable "b" in the third line of code: "b" is
still a reference to the first instance of String, which has the value
"Old Value". "a" and "b" now point to different memory locations.

This is _exactly_ what happens with reference types:

ArrayList x = new ArrayList();
ArrayList y = x;
x = new ArrayList();
x.Add("Hello world");

The first line of code creates and empty array list and points "x" to
it. The second line of code points "x" and "y" to the same array list.
The third line of code points "x" to a new array list that is distinct
from the first one. The last line modifies the second array list to
contain one item: a reference to a string with the value "Hello world".
The array list pointed to by "y" will still be the original, empty one,
so x.Count will be 1, but y.Count will be 0.

The different with the String type is that you don't see that "new"
operation taking place. It happens behind the scenes, which can be
confusing.

On top of this, there is one _true_ difference between Strings and most
other reference types that _does_ make Strings look like value types:
comparing two Strings with the "==" operator compares their _values_,
not their addresses (references), whereas comparing two object
references with "==" usually compares addresses, not values.

The second bit of confusion in your question relates to the fact that
objects are not, in fact, _passed by reference_ to methods. Instead,
object references are passed by value, which is exactly what happens
with String. To understand the difference, read Jon Skeet's excellent
page on parameter passing in C#:

http://www.yoda.arachsys.com/csharp/parameters.html

Suffice to say that your question would have been more interesting if
in your method changeString() you had said:

field.Replace("l", "i");

and asked why the resulting output was not "Oid Vaiue" instead of "Old
Value". The problem with your original example is that setting "field"
to refer to a new object would _never_ change testField back in Main,
regardless of what kind of object "field" was declared to be. The only
way to make that happen is to do this:

changeString(ref testField);
...
private static void changeString(ref String field) ...

You will then see that yes, in fact testField changes its value in Main
after changeString completes.



Relevant Pages

  • Re: Complex Specified Information - Pitman Formula
    ... Therefore a significant match between a reference and a test ... string is good evidence of non-random production. ... and there are no finite algorithms to compute their digits. ... probabilities of the different symbols the information source can produce. ...
    (talk.origins)
  • Re: String Reference Type
    ... All unary and binary operators have predefined implementations that are ... Therefore its always allocated in the heap and a variable of string ... As with all classes in this case y and x both reference the same String ... language depandant matter as below. ...
    (microsoft.public.dotnet.framework.aspnet)
  • Re: Abstract class variables question
    ... But as I think you've seen elsewhere in this thread, a value type can exist inside a class and in that case the value type is stored in the heap with the rest of the class instance. ... But as far as the "faster" goes, yes...to some extent value types have less overhead than reference types, and so can perform better in certain cases. ... Well, that would be true for a string object too, if there was any way to actually change a string. ... Seriously though, it is practically always the case that when you are writing an assignment to a reference, you're replacing the reference held by the variable. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: 6502s and Symbol Tables
    ... Symbols are stored sequentially in memory as Pascal String, ... Symbol lookup works as a binary search via the sorted vector ... Along with a reference counted, handle based memory manager, I can quickly add a string into the table and return a handle to it's memory. ...
    (comp.sys.apple2.programmer)
  • Re: 6502s and Symbol Tables
    ... Symbols are stored sequentially in memory as Pascal String, ... Symbol lookup works as a binary search via the sorted vector ... Along with a reference counted, handle based memory manager, I can quickly add a string into the table and return a handle to it's memory. ...
    (comp.sys.apple2.programmer)