Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

string is reference type but why it work as a value type when it's assignment updated

Tags:

string

c#

This is a simple code snippet, which make me a bit confuse:

string s1 = "abc";
string s2 = s1;
s2 = "123";
Debug.Log(s1 + ":" + s2);

The debug result is abc:123

So why s1 is not updated to 123 as s1 and s2 contain same reference and if one variable update it then, second will get updated automatically.

like image 770
Muhammad Faizan Khan Avatar asked Mar 29 '16 06:03

Muhammad Faizan Khan


People also ask

Is String a value type or reference type?

String is a reference type, but it is immutable. It means once we assigned a value, it cannot be changed. If we change a string value, then the compiler creates a new string object in the memory and point a variable to the new memory location.

Why is String not a value type?

Strings aren't value types since they can be huge and need to be stored on the heap. Value types are stored on the stack as in the CLR implementation by Microsoft. Stack allocating strings would break all sorts of things.

What is the difference between a reference data type and a value data type?

A Value Type holds the data within its own memory allocation and a Reference Type contains a pointer to another memory location that holds the real data.

What is the main difference between a value type and a reference type?

There are two kinds of types in Visual Basic: reference types and value types. Variables of reference types store references to their data (objects), while variables of value types directly contain their data.


2 Answers

This is a common misunderstanding of the use of references.

s1 is a reference type but its content is a value. You could think all variables are value types, but the way the compiler handles them varies based on value or reference type.

    string s1 = "abc"; 

s1 is equal to the address where "abc" is stored, let's say 0x0000AAAA

    string s2 = s1; 

s2 points to the same address as s1 hence, its value is the same as s1. Both have values 0x000AAAA

    s2 = "123"; 

Strings are immutable, meaning you cannot modify a string, anytime you assign a new value or a modification, you are creating a new string somewhere else in memory while the previous one gets ready for GC, if needed (not in our case actually). At that point, s1 still has value 0x0000AAAA while s2 has a new one 0X0000BBBB.

    Debug.Log(s1 + ":" + s2);

Since both points at different contents, they print different results.

It is only a reference type because the value contained in the variable is not meant to be used as is but is meant to send the pointer to an address location in memory where the actual object is stored.

Except if you use out/ref (the & in C++) then it is implied that the value of the variable is to be used (the address), most likely as a parameter.

Note that this behaviour is the same with any objects, not only string.

Dog dogA = new Dog();
Dog dogB = dogA;
dogA.name = "Wolfie"; // Affect both since we are dereferencing
dogA = new Dog(); // dogA is new object, dogB is still Wolfie

EDIT: OP required explanation on ref/out.

when you want to change an object you would think of the following:

void ChangeObject(GameObject objParam)
{
   objParam = new GameObject("Eve");
}

void Start(){
    GameObject obj = new GameObject("Adam");
    ChangeObject(obj);
    Debug.Log(obj.name); // Adam...hold on should be Eve (??!!)
}

ChangeObject gets a GameObejct as parameter, the compiler copies the value contained in obj (00000AAAA) onto objParam, it makes a copy of it and both now have same value.

Within the method, objParam is given a new value and is no more related to the obj outside of the method. objParam is local to the method and is removed on completion (the game object is still in the scene but the reference is lost).

If you wish to change obj within the method:

void ChangeObject(ref GameObject objParam)
{
   objParam = new GameObject("Eve");
}

void Start(){
    GameObject obj = new GameObject("Adam");
    ChangeObject(ref obj);
    Debug.Log(obj.name); // Yeah it is Eve !!!
}

this time, it was not the value of obj that is passed but the address of obj. So obj may contain 0x0000AAAA but its own address is 0x0000AABB, then objParam's value is now 0x0000AABB and changing objParam means changing the value stored at 0x0000AABB.

out and ref works the same, only that out requires that a value is assigned within the method, while ref can leave the method without affect the given parameter.

like image 83
Everts Avatar answered Oct 30 '22 06:10

Everts


String is Immutable. When you assign string s1 = "abc", you are assigning new object reference created by string literal abc to the reference of s1.
So when you assign s2 = "123"; , s2 will be referencing to new object created by string literal "123".
Hope this helps!!

like image 21
kranthiv Avatar answered Oct 30 '22 08:10

kranthiv