views:

72

answers:

4

When reference variable can be passed by reference :

    class Example
    {
        public string str="Demo";

        public int[] intValues={1,3,4,5};

       public static void StrPassing(string someStr)
        {
            string otherStr="Changed!";
            someStr=otherStr;
        }

        public static void NumPassing(int[] a)
        {
            a[2] = 115;
        }

    }


       static void Main(string[] args)
        {
            Example ex = new Example();
            Example.StrPassing(ex.str);
            Example.NumPassing(ex.intValues);

            foreach (int i in ex.intValues)
            {
                Console.WriteLine(i);
            }

            Console.WriteLine(ex.str);
            Console.ReadLine();
        }

the value of intValues[2] is changed as 115 as the reference is being passed.But the value of the string "str" (demo) is not changed to "Changed!".What is the reason for it?.can i take it as Arrays are passed by reference and other reference types are passed by value?

+6  A: 

Whatever you pass to a method as arguments is passed by value which, for reference types, means that a reference is passed by value. So you can't change the object to another one but you can surely change its contents (because that doesn't change the actual reference, just some memory elsewhere).

As your example with the array demonstrates you take the array reference (but don't change it) and change a value in the array. This is just like taking some object and changing a property value. You can do this just fine from within a method too.

If you want to change a string, which is an immutable object in .NET, then you need to resort to ref parameters:

public static void StrPassing(ref string someStr)
{
    string otherStr="Changed!";
    someStr=otherStr;
}

And call it like this:

string foo = "foo";
StrPassing(ref foo);
Console.WriteLine(foo); // should print "Changed!"

The ref keyword ensures that your method gets the actual reference to the string and can change it, instead of just a copy of the reference. So then you can replace the object by an entirely new one.

To come back to your array: You'd have a hard time too, to change the passed array to an entirely different array:

public static void NumPassing(int[] a)
{
    a = new int[15];
}

wouldn't work too because then you'd try exactly the same as changing a string to an entirely different string.

Joey
I don't think "by reference by value" is a particularly helpful term - separate what's being passed (a reference) from how it's being passed (by value). The leading "by" just adds to the confusion IMO.
Jon Skeet
You're right. I changed it to something more understandable (I hope). Resembles your words more now. Aaaand there goes my accepted answer. Drat.
Joey
+1  A: 

What you'd need to do is change the signature for StrPassing to look like this:

public static void StrPassing(ref string someStr)
jasonh
A: 

Strings are special in C#. They are immutable reference types which makes they exhibit similar behavior as value types.

Here's a good discussion.

colithium
Being immutable doesn't make them *that* special - in particular, the compiler doesn't change how they're passed or anything like that.
Jon Skeet
+4  A: 

You need to distinguish between changing which object a variable refers to and changing *the content of the object".

In this code:

public static void StrPassing(string someStr)
{
    string otherStr="Changed!";
    someStr=otherStr;
}

... you are changing the value of someStr. You're not making any change to the string that someStr originally refers to. Indeed, you can't because strings are immutable. (If it were a StringBuilder, you could set the length to 0 and then append "Changed!")

Changing the value of someStr has no effect because the argument (ex.str) was passed by value. (The value in question is a reference, but that doesn't mean it's passed by reference.)

Now compare that with this code:

public static void NumPassing(int[] a)
{
    a[2] = 115;
}

Here you're not changing the value of a - you're changing the contents of the array that a refers to.

In short, unless you use ref/out, arguments will be passed by value - but for reference types that value is just a reference.

I have an article on parameter passing which goes into all of this in a lot more detail.

Jon Skeet