andrey.shedko
andrey.shedko

Reputation: 3238

Is really argument passing by value?

I'm reading John Skeet's book "C# in Depth". He said on page 74 that everybody suppose that arguments passing to function by reference, meanwhile it's passing by value and as example he shows this code that must prove StringBuilder in calling code wasn't changed. meanwhile inside our function StringBuilder instance changed.

private static void SayHello(StringBuilder s)
 {
   s.AppendLine("Hello");
 }

But my experiment showing that StringBuilder object got changes - we will see "Hello" in console. What is wrong here? Or what is wrong with my understanding of this example?

       private static void Main(string[] args)
        {
           var s  = new StringBuilder();
            Console.WriteLine(s.ToString());
            SayHello(s);
            Console.WriteLine(s.ToString());
            Console.ReadLine();
        }

        private static void SayHello(StringBuilder s)
        {
            s.AppendLine("Hello");
        }

Upvotes: 4

Views: 211

Answers (2)

InBetween
InBetween

Reputation: 32790

Consider the following analogy:

  1. You buy a new apartment (new StringBuilder()) and you get a key (s) that grants you access.
  2. You hire a cleaner (s.AppendLine) and you give him a copy of your key so he can access your apartment and clean it up.
  3. The cleaner uses the copy of your key, cleans up your apartment and, because he feels like it, reprograms the key to open some other apartment.
  4. You finish your daily work and come back home. Your key opens the door to your apartment just fine and you find it clean.

That's basically what happens when you pass a reference type by value.

Now consider the following:

  1. You buy a new apartment (new StringBuilder()) and you get a key (s) that grants you access.
  2. You hire a cleaner (s.AppendLine) and you give him your key so he can clean up your apartment.
  3. The cleaner cleans up your room and, becauase he feels like it, reprograms the key you gave him to open some other apartment. He leaves your key under the door mat.
  4. You finish your daily work and come back home. You try to use your key but the door wont open. Through a window you can see your apartment is clean.

Thats what happens when you pass a reference type by reference.

Upvotes: 1

mybirthname
mybirthname

Reputation: 18137

After reading the page, what he is saying is this.

Now remember that the value of a reference type variable is the reference, not the object itself. You can change the contents of the object that a parameter refers to without the parameter itself being passed by reference.

    public static void Main()
    {
        var s = new StringBuilder();
        Console.WriteLine(s.ToString());
        SayHello(s);
        Console.WriteLine(s.ToString());
        Console.ReadLine();
    }

    private static void SayHello(StringBuilder s)
    {
        s.AppendLine("Hello");
        s = null;
    }

    //output will be Hello

When this method is called, the parameter value (a reference to a StringBuilder) is passed by value. If I were to change the value of the builder variable within the method—for example, with the statement builder = null;—that change wouldn’t be seen by the caller, contrary to the myth.

So pretty much he explain that you can't destroy the object StringBuilder in SayHello, you can just change the content of this object. I didn't know that too.

EDIT: About your comment

So pretty much when you pass s in SayHello, you are creating new reference and both reference in Main method and in SayHello refer to the same object. But they exist like 2 different references.

If you write in

private static void SayHello(StringBuilder s)
{
    s.AppendLine("Hello");
    s = new StringBuilder();

}

The reference of the s in SayHello will point to another object, but this will not change anything in Main method because the reference is pointing to previous object in which you wrote Hello. So again the output will be Hello.

If you want to pass the exact reference you should use ref

So if you write

private static void SayHello(ref StringBuilder s)
{
     s.AppendLine("Hello");
     s = null;
     //you will receive an exception in Main method, because now the value in the reference is null.
}

Upvotes: 4

Related Questions