开发者

Question about Referencing Strings in C#

Quick question.

Take the following code sample:

ArrayList arrayList = new ArrayList();
string testString = "";
testString = "test";
arrayList.Add(testString);
开发者_C百科

In that code sample, if I were to do the following:

arrayList[0] = "anotherTest";

Would testString be changed to anotherText or would it remain the same? Is it that object that is put in or a copy of it, another string?

Thanks, Christian


Before:

         

Question about Referencing Strings in C#

After:

         

Question about Referencing Strings in C#

  • Only the value of arrayList[0] is changed to a reference to "anotherTest". The value of the testString variable remains unchanged.

  • String is a reference type. This means both the testString variable and arrayList[0] each (independently) hold a reference to the objects "test" and "anotherTest", not the value itself.

  • Changing testString or arrayList[0] from one string to another string does not modify the original string. Strings are immutable. Only the reference to the string object is changed.


There are 2 objects here: "test" and "anotherTest".

Stage 1:

arrayList.Add(testString) //Adds the reference stored in testString 
                          //to the end of arrayList.

After the execution of this line, arrayList[0] also contains a reference to "test" (since at this stage, testString contains a reference to the object "test").

You can check this:

Console.WriteLine(object.ReferenceEquals(testString, arrayList[0])); //outputs true

Stage 2:

arrayList[0] = "anotherTest"; //stores a reference to the object "anotherTest" in
                              //arrayList[0]

We have not changed testString at all. It still references "test". You can chech that the references stored in arrayList[0] and testString are different:

Console.WriteLine(object.ReferenceEquals(testString, arrayList[0])); //outputs false

testString -> stores reference to "test"
arrayList[0] -> stores reference to "anotherTest"


When you have completed the first code block

 ArrayList arrayList = new ArrayList(); 
 string testString = "";
 testString = "test";
 arrayList.Add(testString);

you have two references one to the arrayList and one to the testString.

The first element in arrayList references the same object as testString, that is the string with the value "test".

The arraylist does contain a reference to the testString object, but the arraylist item 0 and the testString variable both references the same object.

When you do the assignment

    `arrayList[0] = "anotherTest";`

you implicitly instantiates a new string object containing "anotherTest". This object is stored in the array item with index null.

So after the second block arraylist item 0 references the new string object and testString continues to reference the original string.


In your example you are updating the first index of the list it self, not the original string that was added to the list.

even if you are not using a string for example a Bitmap class or even an int struct:

int i = 14;

List<int> myList = new List<int>();
myList.Add(i);

myList[0] = 3;

this will not affect the original i and it will remain 14.

Another thing you should know that the string class -unlike other classes in general- is immutable so:

string s1 = "some text";
string s2 = s1;
s2 += " another text";

the s1 will stay remains unchanged.

A normal class will not be immutable, like:

class MyClass
{
    public string MyString;
}

MyClass class1 = new MyClass();
class1.MyString = "Some String";
MyClas class2 = class1;
class2.MyString = "Other String";

This will effect the class1 string as will so it is now "Other String", and that because the classes are referance types.


In fact none of the three answers so far are very accurate.

The testString variable always holds a reference to "test" in the example. It never changes.

What's more important is that ArrayList also is a container that contains references to objects. So when you assign "anotherTest" to the 0th element, you in fact make the 0th element reference a different string object. This doesn't change the value of testString.


Well, you could always run the code to find out ;).

The answer is that testString would not be changed. @dtb's answer explains why. I'll approach a different aspect of the problem, regarding your "Is it that object that is put in or a copy of it, another string?" question.

Let's break down what's going in your code:

  • testString contains a reference to "test".
  • Calling arrayList.add(testString) sets arrayList[0] to be a reference to "test".
  • Doing arrayList[0] = "anotherTest" sets arrayList[0] to be a reference to "anotherTest".

So, as you can see, there is no copying going on, ever. Strings are not copied, or (as some other answers have put it) "passed by value".


If your question was about a value type, like a struct or even just int, then the answer would still be that testInt is not changed, but in that case the reason would be that copying has occurred: value types are "passed by value", and copies of them do get created when you use the = operator.


The short answer to your question is "no".

Why? Because Strings are immutable.

Here's why:

From Wikipedia:

If an object is known to be immutable, it can be copied simply by making a copy of a reference to it instead of copying the entire object. - Wikipedia.org

Let's step through an example:

var a = "Testing";
var b = a;

Here, you've already got a string ("Testing") sitting at some location in memory (let's say location 0x001. So, the actual value of "a" becomes 0x001 on the first line.

And we set b = a on the second line... so b also gets set to 0x001 (since we're copying references).

Now, suppose we do this:

a = "Again";

Here, we have another string ("Again") sitting at some different location in memory (let's say location 0x022).

We know strings are immutable... so what happens here? Well... that means we assign by reference. So, the value of "a" becomes 0x022.

What does this mean for "b"?

It means, any variables pointing to 0x001 ("Testing") will STILL point to 0x001... so, in this case, "b", remains UNCHANGED.

And only "a", which we updated by changing it's reference will point to 0x022.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜