11

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?

Kyle Baran
  • 1,793
  • 2
  • 15
  • 30

3 Answers3

14

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.

Avi Turner
  • 10,234
  • 7
  • 48
  • 75
  • 1
    Your explanation of ref/out isn't right. First off, it's not even required that they be used on value types, and second, it doesn't have the same semantics as passing a reference by value. Passing a reference by value and a value by reference are actually different (both logically as well as functionally) and this post demonstrates a lack of understanding of the core concepts here. – Servy Jul 01 '13 at 17:06
  • @servy you are correct, I was concentrating on a tree and missed the forest, I guess i paid less attention to it as it was not the main question and gave an example of the main use I do with out/ref... I have updated my answer. do you think it is adequate now? – – Avi Turner Jul 02 '13 at 14:00
  • 1
    Not really. Your explanation doesn't really explain much. If the OP doesn't already understand C++ that example doesn't help, and the ability to re-allocate a reference type is one thing that you can do, but it's not an explanation of what passing by reference *means*. – Servy Jul 02 '13 at 14:08
  • @Servy At this point we disagree. The question was fully answered and the purpose of out and ref is explained. The example is a just bonus -it is not doing any harm, and there is a link for more detailed explanation. Any way, thank you for your comments. I will make an effort to be more precise in the first shot at future answers. – Avi Turner Jul 02 '13 at 17:26
  • 1
    @AviTurner your understanding of ref is flawed. C# does proper pass by reference when you use the ref modifier on parameters. – Talha Sayed Dec 27 '14 at 17:41
  • @TalhaSayed You are wrong. What is being passed is a "pointer to the pointer" which is an address. At the bottom line it is a number that is being passed by value. The address is being the duplicated on the stack, hence - passing by value. This results a pass by reference to the instance of the object (or As I wrote in my answer `what is really being passed to the function is the pointer`) but never the less, the call is being used with a call by value of the address. – Avi Turner Dec 27 '14 at 17:59
  • 1
    @AviTurner Yes, that is exactly how I understand it too. So, isnt that called passing by reference ? Since using the ref parameter it implicitly adds another level of indirection and passes a pointer to a pointer. I know at the end of the day, a value is being passed but since it as a pointer to a pointer which is passed implicitly, isn't this concept called "passing by reference". If not this, then what would be called passing by reference ? – Talha Sayed Dec 27 '14 at 19:47
  • @TalhaSayed Yes, this is "passing by reference". It might be very easy to grasp it once you are already familiar with the concept, but Remember, the PO does not have your prior knowledge, or else he would not be posting the question. In the post I'm using an explanatory tactic which includes what happens at the bottom line, which is passing an address by value. It seems that the tactic worked, the PO was happy with the explanation. – Avi Turner Dec 28 '14 at 03:48
5

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#)

Sabashan Ragavan
  • 728
  • 1
  • 5
  • 14
0

Tragically, there is no way to pass an object by value in C# or VB.NET. I suggest instead you pass, for example, New Class1(Object1) where Object1 is an instance of Class1. You will have to write your own New method to do this but at least you then have an easy pass-by-value capability for Class1.