Basic Question: string reference type

  • Thread starter Thread starter Nader
  • Start date Start date
N

Nader

Hello all,

In C# string is a reference type but I learned that string is different from
other reference types such as class. For example, if you pass a string
argument to a method and then change the value in that method the
modification will not be visible outside the method. However this is not
true for classes. In my example I am not using ref keyword.

Thanks for feedback.
 
Correct, the terminology used is that strings are immutable reference types.
So they don't behave quite like other reference types. Once defined, a
string cannot change value. However, a variable holding a reference to a
string may certainly be assigned a new string object. This is often
encountered in the following:

string mystr = "Good morning.";
mystr.Replace ("morning", "evening"); // does nothing
mystr = mystr.Replace ("morning", "evening"); // expected behavior

Not really about strings in particular, but here's some good references on
reference / value types if you want more info:

http://www.pobox.com/~skeet/csharp/parameters.html
http://www.pobox.com/~skeet/csharp/memory.html
and
http://www.mag37.com/csharp/articles/ValueAndReferenceTypes.html
(by your's truly)
 
Thanks Mike,

I was just wondering what is happening behind the scenes that make strings
act differently.
 
Nader said:
Thanks Mike,

I was just wondering what is happening behind the scenes that make strings
act differently.

I don't think there's really much "beind the scenes" magic. There is no
method that allows you to change a string, therefore it is immutable. You
can make your own class that is immutable pretty easily:

(pardon this code, it's all written on the fly in the newsreader, so there
are surely some grammatical mistakes)

public sealed class ImmutableComplexNumber {
public ImmutableComplexNumber (double real, double imag) {
this.real = real;
this.imag = imag;
}
double real;
double imag;

public double AbsoluteValue {
get { return (real * real) + (imag * imag); }
}

public ImmutableComplexNumber Add (ImmutableComplexNumber x) {
return new ImmutableComplexNumber (this.real + x.real, this.imag +
x.imag);
}
}

There is no way for a user to actually change the value of an instance of
ImmutableComplexNumber once the've created it. Even add will simply return a
new number. The class is sealed, real and imag are private, and there are no
publicly accesible methods (other than the constructor) that will change
those two private fields. Pretty much the same for strings.

Now strings have the additional benefit of being known by the CLR so it can
do cool tricks like string interning and other optimizations. Here's an
article I've run across in the past that has some details on inner workings
of the string class.

http://www.wintellect.com/resources/newsletters/2002/Jan2002.aspx
http://www.codeproject.com/dotnet/strings.asp

Hope that answers your questions.
 
Nader said:
In C# string is a reference type but I learned that string is different from
other reference types such as class.

No it's not. Not really.
For example, if you pass a string
argument to a method and then change the value in that method the
modification will not be visible outside the method.

Changing the value of a reference variable does *not* make any change
in the object itself.
However this is not true for classes.

Yes it is.

Here's an example of what I think you mean:

using System;

public class Test
{
static void Main()
{
string x = "hello";
Foo (x);
Console.WriteLine (x);
}

static void Foo(string y)
{
y = "world";
}
}

The above prints hello, but you'd expect it to print world. Now, that's
exactly the same as:


public class Test
{
static void Main()
{
ArrayList al = new ArrayList();
al.Add ("hello");
Foo (al);
Console.WriteLine (al[0]);
}

static void Foo(ArrayList y)
{
y = new ArrayList();
y.Add ("world");
}
}

Note that we're changing the *value of y* in both cases, not the data
within the object that the original reference points to.

Strings are absolutely reference types - but you need to be clear about
the difference between changing which object a variable's value refers
to and changing the *contents* of the object a variable's value refers
to.

See http://www.pobox.com/~skeet/csharp/parameters.html and
http://www.pobox.com/~skeet/csharp/memory.html for more details.
 
Michael Mayer said:
Correct, the terminology used is that strings are immutable reference types.
So they don't behave quite like other reference types.

They do! They behave exactly like other reference types. It so happens
that you can't change them, but that's in common with a lot of other
reference types, and it's not "special" at all - it's not like there's
another rule to learn, it's just applying the normal rules.

The only "tricky" thing about strings is string literals - and they're
just references to string objects which will exist by the time you use
the literal, and are interned so that the same literal will always
refer to the same instance within an application.
 
Please look at the piece of code below.

Even though my argument list in test(...) method does not include ref
keyword the result is visible in the Main() function and you get "Hello from
testClass".

This is not the case when I replace myString class with a simple string.

using System;

class myString
{
public myString()
{
str1 = "Hello from myString";
}
public string str1;
}

class testClass
{
public void test(myString astr)
{
astr.str1 = "Hello from testClass";
}
}

class theApp
{
public static void Main()
{
testClass tc = new testClass();
myString ms = new myString();
tc.test(ms);
Console.WriteLine("{0}", ms.str1);
}
}
 
Your class myString is NOT an immutable class (the way string is) since you
made str1 a public field of class myString (see my previous post with the
complex number example - this would be an immutable class).

I would suspect that if you had read those articles that Jon and I wrote
(posted previously) they will clear up some of your mis-understanding. I'll
try here briefly, but I must insist that you go read Jon's or my articles (I
think mine is more geared toward a beginner to C#, while Jon's uses more
accurate, technical verbage).

However, we can rewrite your example below to do the same thing as you
mentioned in your first post:

public void test(myString astr)
{
astr = new myString ("Hello from testClass";)
}

Note that here in my version of test, I am trying to change the VALUE of
astr (which is a reference to a class). Since astr is passed by value, this
has no affect in the calling function. This is what you mentioned doing in
your first post - changing a string in a method, probably as follows:

public void testOP (string mystring)
{
mystring = "new string";
}

In your version (below) you are not changing the value of astr, but rather,
the value of str1 in an instance of myString class. Since both testClass and
theApp reference that same instance, you will see the change both places.

Another note, you might find the following useful on naming conventions, it
will make your code more immediately readable by others (that is, classes
and methods should be capitalized in C#)
http://msdn.microsoft.com/library/d...en-us/cpgenref/html/cpconnamingguidelines.asp
 
Jon Skeet said:
They do! They behave exactly like other reference types. It so happens
that you can't change them, but that's in common with a lot of other
reference types, and it's not "special" at all - it's not like there's
another rule to learn, it's just applying the normal rules.

Jon,
My first post didn't say exactly what I meant for it to have said. I think
my second post clarified what I meant a little better.

I was trying to get across something you mentioned on one of your pages:

"Note that many types (such as string) appear in some ways to be value
types, but in fact are reference types. These are known as immutable types."

I should have mentioned that they still follow all the rules of reference
types, with the added benefit that, like value types, you don't have to
worry about them changing when passed as parameters to other methods.
 
Back
Top