Array as function parameter, on stack or on heap?

Marc W

Member
Joined
Oct 8, 2014
Messages
8
Programming Experience
Beginner
Say I have this: "double CalculateSomething(double[,] VeryLargArray)", is the array actually referenced to memory on the heap, or is the whole array placed on the function stack? If the latter, is there a way to prevent this, if your array is really large? I think if the array is really large, it would become inefficient to copy all that data to the stack.
 
A small test program can demonstrate that an array is passed by reference.

            int[] ar = new int[5];
            for (int i = 0; i < ar.Length; i++)
            {
                ar[i] = i * 2;
            }

            somefunc(ar);



        private void somefunc(int[] ar)
        {
            for (int i = 0; i < ar.Length; i++)
            {
                ar[i]+=1;
            }
        }

If you stop the code after the call to somefunc() in the first code block, all array elements are incremented by one. This would not be the case if the array was passed by value. So there is no copying.

This does not answer the question if it's on the heap or on the stack; and I don't know the answer for C# for sure. But seeing that arrays are instantiated (using the new keyword), my common sense tells me that the original array (created in the first code block) is on the heap.
 
A small test program can demonstrate that an array is passed by reference.
That's a good way to confuse the issue. Unless you use the `ref` keyword, any method argument is passed by value. If the object is a reference type, the value that gets passed is a reference. When you pass a variable to a method as an argument, the default mechanism is always to create a copy the contents of that variable and pass that to the method. If the variable is a value type then the contents is a value so that value gets copied and passed to the method. If the variable is a reference type then the reference gets copied and passed to the method. It's that simple. Whatever the variable contains is copied and a reference type variable never contains an object so a reference type object is never copied.
 
Okay, but is "int[] ar" a reference type or a value type? I am a little confused here. If I google I find that "Arrays are referece types in C#", but I have some doubts since in C++ something like "int[]" is passed by value, and you should pass it as a pointer for performance. Does something like that apply for C#? Also you in C# you have the Array type, but is int[] of that same type? Like you have the int primitive and the a class corresponding to int if it is boxed.
 
Okay, but is "int[] ar" a reference type or a value type? I am a little confused here. If I google I find that "Arrays are referece types in C#", but I have some doubts since in C++ something like "int[]" is passed by value, and you should pass it as a pointer for performance. Does something like that apply for C#? Also you in C# you have the Array type, but is int[] of that same type? Like you have the int primitive and the a class corresponding to int if it is boxed.

All arrays are reference types. References exist so that you have something that gets treated like it's an object from the outside and like it's a pointer on the inside. It's much like properties are actually methods but they appear to be a field from the outside; references are actually pointers but appear to be objects from the outside. It's not quite that simple but it may help to think of it like that. The only question you have to ask is whether something is a reference type, i.e. class or delegate, or a value type, i.e. structure or enumeration. There is no in between; it's either one or the other and that tells you how it gets used.
 
Okay, if there is no copying, it makes no use adding ref, similar to passing it as a pointer in C++, for performance reasons, right? Since that is what triggered my question.
The rules about when to use `out` and `ref` are very simple:

If you want to use a parameter only to pass a value or object out of a method then use `out`.
If you want to pass in one value or object and pass out another then use `ref`.
If you want to be able to modify an existing value type inside the method and have that change affect the original value then use `ref`.
In all other cases, use the default mechanism, which is passing by value.

That is all you have to consider. Only value type objects get copied when passed by value and that should never be an issue because you should be following Microsoft's recommendation that value types should only ever be 16 bytes or smaller.
 
never be an issue because you should be following Microsoft's recommendation that value types should only ever be 16 bytes or smaller.
Okay. But what if I encounter the hypothetical situation where a programmer before me has made an enormous struct, and puts it in a function parameter? .. Actually I think you are going to say: refacture it to a class, dont use ref as a performance patch, right.? But theoretically using a ref would help there.
 
Okay. But what if I encounter the hypothetical situation where a programmer before me has made an enormous struct, and puts it in a function parameter? .. Actually I think you are going to say: refacture it to a class, dont use ref as a performance patch, right.? But theoretically using a ref would help there.

Sometimes you need to do the wrong thing for pragmatic reasons and that would be one of those situations. Such situations should be extremely rare though.
 
Back
Top Bottom