Passing objects by reference vs value

17,114

Solution 1

What I don't understand is what happens when I invoke a method, what actually happens. Does new() get invoked? Does it just automagically copy the data? Or does it actually just point to the original object? And how does using ref and out affect this?

The short answer:

The empty constructor will not be called automatically, and it actually just points to the original object.
using ref and out does not affect this.

The long answer:

I think it would be easier to understand how C# handles passing arguments to a function.
Actually everything is being passed by value
Really?! Everything by value?
Yes! Everything!

Of course there must be some kind of a difference between passing classes and simple typed objects, such as an Integer, otherwise, it would be a huge step back performance wise.

Well the thing is, that behind the scenes when you pass a class instance of an object to a function, what is really being passed to the function is the pointer to the class. the pointer, of course, can be passed by value without causing performance issues.

Actually, everything is being passed by value; it's just that when you're "passing an object", you're actually passing a reference to that object (and you're passing that reference by value).

once we are in the function, given the argument pointer, we can relate to the object passed by reference.
You don't actually need to do anything for this, you can relate directly to the instance passed as the argument (as said before, this whole process is being done behind the scenes).

After understanding this, you probably understand that the empty constructor will not be called automatically, and it actually just points to the original object.


EDITED:

As to the out and ref, they allow functions to change the value of an arguments and have that change persist outside of the scope of the function.
In a nutshell, using the ref keyword for value types will act as follows:

int i = 42;
foo(ref i);

will translate in c++ to:

int i = 42;    
int* ptrI = &i;
foo(ptrI)

while omitting the ref will simply translate to:

int i = 42;
foo(i)

using those keywords for reference type objects, will allow you to reallocate memory to the passed argument, and make the reallocation persist outside of the scope of the function (for more details please refer to the MSDN page)

Side note:
The difference between ref and out is that out makes sure that the called function must assign a value to the out argument, while ref does not have this restriction, and then you should handle it by assigning some default value yourself, thus, ref Implies the the initial value of the argument is important to the function and might affect it's behaviour.

Solution 2

Passing a value-type variable to a method means passing a copy of the variable to the method. Any changes to the parameter that take place inside the method have no affect on the original data stored in the variable.

If you want the called method to change the value of the parameter, you have to pass it by reference, using the ref or out keyword.

When you pass a reference-type parameter by value, it is possible to change the data pointed to by the reference, such as the value of a class member. However, you cannot change the value of the reference itself; that is, you cannot use the same reference to allocate memory for a new class and have it persist outside the block. To do that, pass the parameter using the ref (or out) keyword.

Reference: Passing Parameters(C#)

Share:
17,114
Kyle Baran
Author by

Kyle Baran

I'm just a programming graduate looking to expand his knowledge in C#, and maybe make a game one day.

Updated on June 05, 2022

Comments

  • Kyle Baran
    Kyle Baran almost 2 years

    I just want to check my understanding of C#'s ways of handling things, before I delve too deeply into designing my classes. My current understanding is that:

    • Struct is a value type, meaning it actually contains the data members defined within.
    • Class is a reference type, meaning it contains references to the data members defined within.

    • A method signature passes parameters by value, which means a copy of the value is passed to the inside of the method, making it expensive for large arrays and data structures.

    • A method signature that defines a parameter with the ref or out keywords will instead pass a parameter by reference, which means a pointer to the object is provided instead.

    What I don't understand is what happens when I invoke a method, what actually happens. Does new() get invoked? Does it just automagically copy the data? Or does it actually just point to the original object? And how does using ref and out affect this?