views:

200

answers:

6

Assume the following code, without any ref keyword, that obviously won't replace the variable passed, since it's passed as value.

class ProgramInt
{
    public static void Test(int i) // Pass by Value
    {
        i = 2; // Working on copy.
    }

    static void Main(string[] args)
    {
        int i = 1;
        ProgramInt.Test(i);
        Console.WriteLine(i);
        Console.Read();

        // Output: 1
    }
}

Now to have that function working as expected, one would add the ref keyword as usual:

class ProgramIntRef
{
    public static void Test(ref int i) // Pass by Reference
    {
        i = 2; // Working on reference.
    }

    static void Main(string[] args)
    {
        int i = 1;
        ProgramInt.Test(ref i);
        Console.WriteLine(i);
        Console.Read();

        // Output: 2
    }
}

Now I'm perplex as to why array members when passed in functions are implicitly passed by reference. Aren't arrays value types?

class ProgramIntArray
{
    public static void Test(int[] ia) // Pass by Value
    {
        ia[0] = 2; // Working as reference?
    }

    static void Main(string[] args)
    {
        int[] test = new int[] { 1 };
        ProgramIntArray.Test(test);
        Console.WriteLine(test[0]);
        Console.Read();

        // Output: 2
    }
}
+1  A: 

Can you imagine passing a 2 million element array by value? Now imagine that the element type is decimal. You will have to copy around 240MB 30.5175781MB of data.

ChaosPandion
+9  A: 

No, arrays are classes, which means they are reference types.

bright
Normally, you can press F12 on any type to find out. If the declaration says “class”, it’s a reference type; if it says “struct”, it’s a value type. Unfortunately, it doesn’t let you do this with arrays, which is a shame. So you just have to remember that arrays are reference types, even if it’s an array of a value type.
Timwi
Clear and concise, thanks.
Lazlo
A: 

As indicated by the MSDN reference, arrays are objects (System.Array is the abstract base type of all arrays) and objects are passed by reference.

thomasvdb
I was going to mention `System.Array`, but then I remembered that `System.ValueType` and `System.Enum` are reference types too, and yet the value types and enums that logically derive from them aren’t.
Timwi
+2  A: 

Arrays are not passed by reference. References to arrays are passed by value. If it's necessary to change WHAT array a passed-in array variable points to (e.g. to change the size of the array), the variable must be passed by reference.

supercat
A: 

Other than basic data types you cannot pass anything else as pass by value, Array is collection of basic data types also allowing passing by value on collection would create multiple copies of collection which would be bad on performance.

Kiran Bheemarti
Structs are not "basic data types" and they are passed by value.
Eric Lippert
+2  A: 

A good way to remember this is:

  • "ref" makes an alias to a variable
  • an array is a collection of variables; each element is a variable.

When you pass an array normally, you are passing a collection of variables. The variables in the collection do not change.

When you pass an array with "ref" then you are giving a new name to the variable that contains the array.

When you pass an array element normally you are passing the value in the variable.

When you pass an array element - a variable - with "ref", you are giving a new name to that variable.

Make sense?

Eric Lippert
I personally like this above saying addresses but still most people don't get this. Here is a way I described it using a dog as an analogy but it seems really lame: http://stackoverflow.com/questions/3366650/does-var-onload-mean-that-it-should-run-when-page-is-loaded/3366783#3366783
ChaosPandion
Personally I don’t like the phrasing of “giving a new name”. For some reason, it just doesn’t ring with me. But I don’t know how novices would perceive it.
Timwi