2

Ok, So I am a beginner in C# and I learned the concept of Reference Type and Value Type. Also I understood that Value type is on Stack where as Reference types are stored in Heap. And then we need to to manually allocate memory to Reference type and all of that. But I am not able to understand below Behaviour. Please guide me.

Example 1:

    var arr1 = new int[3] { 1, 2, 3 }; // memory allocated
    var arr2 = arr1; // another variable created but pointing to same memory in Heap
    arr2[0] = 2; // value in array 2 changed
    System.Console.WriteLine("");
    foreach (var item in arr1)
    {
        System.Console.WriteLine(item);
    }
    System.Console.WriteLine("------------");

    foreach (var item in arr2)
    {
        System.Console.WriteLine(item);
    }

Output as :

            arr1: 2,2,3
            arr2: 2,2,3

Conclusion: Since both were pointing to same memory location. So, when value in Array 2 is changed the value in Array1 also got affected. So far so good.

Now there is one more reference type which is string.

Consider below Example 2:

   var Name = "Mosh";
   var FName = Name;
   FName = "Hello";
   System.Console.WriteLine(Name);
   System.Console.WriteLine(FName);

Output as:

Mosh
Hello

Expected Output:

Hello
Hello

Since I changed the value for FName I was expecting the Name value also to be changed as both must be pointing to same memory location. It's one of the simplest question on SO, I am a beginner so bear with me.

Unbreakable
  • 7,776
  • 24
  • 90
  • 171
  • 1
    How about using the search first? There are actually multiple questions similar to yours. – wp78de Nov 25 '17 at 01:41
  • @wp78de: I read and understood that since String is Immutable and when we assign a brand new value to it, under the hood a new String instance is created a hence a new memory is allocated. Does that mean `FName = "Hello";` writing this piece of code makes the FName to allocate to altogether different memory location than it was at the code ` var FName = Name;` ? – Unbreakable Nov 25 '17 at 01:45
  • Is it safe to say that till `var Name = "Mosh"; var FName = Name;` till here both FName and Name are pointing to same memory location? – Unbreakable Nov 25 '17 at 01:45
  • Assigning two variables to the same value doesn't link them together... if you then change one of the variables to point to a different value, it doesn't automatically update the other one. Arrays are different beasts. You've updated the value of an array index and your two variables are referring to the same array so you'll see the change at the array index for both of them. Nothing here has to do with value vs reference semantics (and it's not always a stack vs heap thing either) – pinkfloydx33 Nov 25 '17 at 02:23
  • You may want to read that too: https://stackoverflow.com/questions/1096449/c-sharp-string-reference-type – wp78de Nov 25 '17 at 02:44

3 Answers3

3

In the .Net Framework a String is an immutable reference type.

Since a String does not have a pre-defined memory size (as the value types that can be stored in the Stack), it can grow large (approx. 2 billion Unicode characters), and requires dynamic memory allocation. When a String object is created, the actual value is stored within dynamic memory, the Heap.

Immutable means, it cannot be changed after it has been created. Every change to a string will create a new string. This is why all of the String manipulation methods return a string.

Reference types have some overhead on construction and destruction and garbage collection, because they are created on the heap. Value types on the other hand have overhead on method calls (if the data size is larger than a pointer), because the whole object is copied rather than just a pointer. Because strings can be much larger than the size of a pointer, they are designed as reference types. Ref.

In your case: When you assign Name to FName: FName = Name both Strings reference the same Object (as shown in the code sample) that contains the string "Mosh" in the Heap. After FName has ben set to another string value it references a different memory location that stores the new string "Hello". Name keeps pointing to original memory location that stores "Mosh" and remains unchanged.

This behavior of String as value type is less obvious when it is used as a parameter that updates the value in the function. As long as the String parameter is not provided by reference it's original value will not be changed (see sample).

using System;

public class Program
{
    public static void Main()
    {
        var Name = "Mosh";
        var FName = Name;
        Console.WriteLine(Object.ReferenceEquals(Name,FName));

        FName = "Hello";
        System.Console.WriteLine(Name);
        System.Console.WriteLine(FName);
        Console.WriteLine(Object.ReferenceEquals(Name,FName));

        TestFunc(Name);
        System.Console.WriteLine(Name); 

        RefFunc(ref FName);
        System.Console.WriteLine(FName);    
    }

    public static void TestFunc(string test)
    {
        test = "after passing";
    }

    public static void RefFunc(ref string test)
    {
        test = "after passing";
    }
}
wp78de
  • 18,207
  • 7
  • 43
  • 71
  • Beside the fact that sstan's answer was already accepted and is perhaps more understandable by a C# starter: I like your elaborate answer. And in addition your sample, where you show the behaviour regarding parameter passing. – Rainer Schaack Nov 25 '17 at 10:08
2

Your confusion comes in part because you see both these statements as somewhat equivalent in nature. They are not!

arr2[0] = 2;

FName = "Hello";

In the first case, the array that arr2 is pointing to is modified. But, arr2's reference to that array is unchanged. So both arr1 and arr2 keep pointing to the same array and both see the changes to the array.

In the second case however, it is not the object that FName points to that is being changed. That is to say, we are not modifying the "Mosh" string in any way. Rather, we are changing FName's reference to point a different memory location where the immutable string "Hello" resides in the heap. After this point, FName no longer points to the same memory location as Name. Name keeps pointing to the "Mosh"'s memory location, which remains unchanged.

sstan
  • 35,425
  • 6
  • 48
  • 66
  • Is it safe to say that till `var Name = "Mosh"; var FName = Name;` till here both FName and Name are pointing to same memory location? – Unbreakable Nov 25 '17 at 02:56
0

A string in a reference type yes, but by C#'s design it will more or less behave like other primitives / value types.

To get the effect you're mentioned you would have to specify that a value is a pointer, something similar to: string* PName = Name;

Your question, "Is it safe to say they are pointing at the same location in memory?" I'm not actually sure, though I know that strings do not have a fixed address in memory, so you cannot use "&" or "GetHashCode" like you can to test this on integers or other types.

Edit 1:

Well I'll be a monkey's uncle, you're right. Try this:

Console.WriteLine(Object.ReferenceEquals(Name,FName)
Jacob M.
  • 750
  • 1
  • 6
  • 21