9
class Test
{
    static void Func(StringBuilder myString)
    {
        myString.Append ("test");
        myString = null;
    }
    static void Main()
    {
        StringBuilder s1 = new StringBuilder();
        Func(s1);
        Console.WriteLine (s1);
    }
}

The output is "Test", why isn't it null?

If s1 is passed by reference to Func(), then why does myString.Append("test") change it, but myString = null does not?

Thanks in advance.

RiggsFolly
  • 93,638
  • 21
  • 103
  • 149
thomas
  • 1,133
  • 1
  • 12
  • 31

5 Answers5

12

You're passing the reference to the object by value.

I.e. the address of the object is passed by value, but the address to the object and the object is the same. So when you call your method, the VM copies the reference; you're just changing a copy.

On myString.Append you're using the copied reference to get to the object (still only one object) which is then changed/invoked.

What you think you're doing is this:

class Test
{
    static void Func(ref StringBuilder myString)
    {
        myString.Append("test");
        myString = null;
    }
    static void Main(string[] args)
    {
        StringBuilder s1 = new StringBuilder();
        Func(ref s1);
        Console.WriteLine(s1);
    }
}

A longer explanation: http://javadude.com/articles/passbyvalue.htm

Lasse Espeholt
  • 17,622
  • 5
  • 63
  • 99
11

if s1 is passed by reference to Func(), then why does myString.Append("test") does change it

Its not passed by references, instead its address value is passed to the function.

Suppose S1 is pointing to a memory location 0x48, This will be passed to Func, where Func parameter myString will start pointing to that location. Later when you Append a text to that location, it gets added. But later when you assign null to myString, it starts pointing to nothing, but the original location remains unchanged.

You should see: Parameter passing in C# by Jon Skeet

Consider the following diagrams. In Step 1, you create a new object of type StringBuilder and let S1 refers to that object.

enter image description here

In Step 2, after passing S1 to Func, now myString also points to the same object in memory.

enter image description here

Later when you Append, text through myString, it updates the original object, since myString is pointing to the memory location held by the object.

In Step 3, when you assign null to the myString it looses the address for StringBuilder object, but this doesn't change anything in the object or the pointer S1.

enter image description here

Habib
  • 219,104
  • 29
  • 407
  • 436
2

In C#, the pointer (reference) to a complex type, by default, is passed by value. You must specify that it is passed by reference, like this:

static void Func(ref StringBuilder myString)
{
    myString.Append ("test");
    myString = null;
}
Karl Anderson
  • 34,606
  • 12
  • 65
  • 80
0

add the ref to the function to pass it by ref.

static void Func(ref StringBuilder myString)
{
    myString.Append ("test");
    myString = null;
}

Then call it like:

Func(ref s1);
CuccoChaser
  • 1,059
  • 2
  • 15
  • 27
0

Because you pass a reference to your StringBuilder s1 to Func. Inside Func, the reference to that same StringBuilder instance is called "myString". You first tell it to do something ("myString.Append("Test")), then set the reference INSIDE Func to null. The result of Append is visible to Main(); the reference being set to null does not influence s1 in Main.

svenv
  • 313
  • 2
  • 9