-2

I thought I understood the difference, but now I'm not so sure. I've read the technical answer several times but I'm not understanding what is happening. I have this example.

class Program
   {
      static void Main()
      {
         int val = 0;

         Example1(val);
         Console.WriteLine(val); // Still 0!

         Example2(ref val);
         Console.WriteLine(val); // Now 2!

         Example3(out val);
         Console.WriteLine(val); // Now 3!
      }

      static void Example1(int value)
         {
             value = 1;
         }

      static void Example2(ref int value)
         {
             value = 2;
         }

      static void Example3(out int value)
         {
           value = 3;
         }
    }

I always thought the difference between default parameters is that if I am passing val into Example1, I can't use assignment.

But with the ref keyword val is still 0, but I have created a reference that is now treated as the variable "value" within Example2(ref val). Am I getting hung up on anything so far? if I had used

int value = 0;
Example1(value);
Console.WriteLine(value); // this would then return 1 correct?

Now then, what is happening with the out keyword? Same thing as ref?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
christopher clark
  • 2,026
  • 5
  • 28
  • 47
  • What do you mean "default parameters"? Do you mean when `ref` or `out` is not used? – John Saunders May 24 '15 at 23:41
  • @JohnSaunders Yes, when ref and out are not used. I wish it were a duplicate, I've read that post multiple times. I still don't get it. – christopher clark May 24 '15 at 23:49
  • Your last code block "If I had used.." is exactly what you're doing in the first 3 lines of your `Main` function in the first code block. – Blorgbeard May 24 '15 at 23:49
  • 2
    I think it _is_ a duplicate, and that you just don't get it. What do you not get? Note that things are a little different between passing a value type (like `int`) and passing a reference type (like an instance of a class). – John Saunders May 24 '15 at 23:50
  • 4
    BTW, please stop using the term "default parameters". That's too close to the C# usage of `public void Method(int val = 1)`, where you don't have to pass a `val` if you want to pass `1`. – John Saunders May 24 '15 at 23:52

3 Answers3

0

In the first example you do not specify that the variable is a reference, and because it is a fundamental type, it just copies the provided number. So value inside Example1 is a copy of value in Main.

The second example uses a reference. This means the both inside the function Example2 and inside Main are refering to the same place in the memory, and therefore the value is transfered, when both entering and exiting the function.

In the third example, the out keyword does the same as the second except that is initialized to be 0 when entered into the function. As a result, it is just a parameter for returning some kind of data. The value is just transfered when exiting the function.

Zinoex
  • 512
  • 2
  • 8
  • 22
  • 1
    You are confusing `ref` with reference types. – John Saunders May 24 '15 at 23:52
  • @JohnSaunders Fundamental types are passed by value by default and all others by reference. `ref` is just a way of explicitly telling it to pass by reference. – Zinoex May 24 '15 at 23:55
  • No, you're wrong again. The distinction is between value types and reference types, and `ref` is not like `ByRef` in Visual Basic. It does not mean "pass by reference". – John Saunders May 24 '15 at 23:56
  • @JohnSaunders No, please check the documentation https://msdn.microsoft.com/en-us/library/14akc2c7.aspx – Zinoex May 24 '15 at 23:57
  • 1
    No, please see "[Types (C# Programming Guide)](https://msdn.microsoft.com/en-us/library/ms173104.aspx)". – John Saunders May 24 '15 at 23:59
  • 1
    "Do not confuse the concept of passing by reference with the concept of reference types. The two concepts are not the same. A method parameter can be modified by ref regardless of whether it is a value type or a reference type. There is no boxing of a value type when it is passed by reference." – John Saunders May 24 '15 at 23:59
  • 1
    "Pass by reference" does not mean that "the variable is a reference". – John Saunders May 25 '15 at 00:00
  • Do you agree that the variable inside the called function refers to the same number as outside the function no matter which of the two are changed? Then they somehow refers to the same location in memory. Of course behind the scene but nevertheless still a reference. – Zinoex May 25 '15 at 00:05
  • No, I agree that changes made to the formal parameter in the method are reflected in the actual parameter in the caller. The mechanism may or may not involve references. Note the similarity to `out`, where you cannot, in fact, access any value from the actual parameter while within the method. `ref` can also be accomplished by copy in-call method-copy out, and `out` can be accomplished by call method-copy out. – John Saunders May 25 '15 at 00:07
  • void Do(MyClass p) { p = new MyClass(); } vs void Do(ref MyClass p) { p = new MyClass(); } Just test this two methods and you will understand the difference. You can change something inside of 'p' without a difference in behavior, but you can't assign a new reference in both cases. – Malmi May 25 '15 at 00:12
  • @Highace2 - John is right. There is a big difference. When you pass a reference variable by `ref` then it is the same as a double-pointer (`**`) in C. If you pass a reference variable without `ref` then it is like a single pointer (`*`). – Enigmativity May 25 '15 at 00:15
0

See if this helps:

No "decorators"

static void Example(int value)
{
    Console.WriteLine("Value is {0}", value);
    value = 99;
}

usage
{
    int value = 10;
    Example(notADefaultValue); // Will print <Value is 10>
    Console.WriteLine("Value is {0}", value); // will print <Value is 10>
}

Summary: Value types (structs/enums/int/double/etc) are not passed in as a reference by default so whatever you do to the variable within a method does not affect the caller. Thus, the "ref" keyword. If you pass a reference type to a method (i.e. a class) and change it's internals, these will affect the caller.

Default parameters:

static void Example(int value = 5)
{
    Console.WriteLine("Value is {0}", value);
}

usage
{
    int notADefaultValue = 10;
    Example(notADefaultValue); // Will print <Value is 10>
    Example(); // will print <Value is 5>
}

Summary: Default values allow you to call a method without explicitly needing to pass parameters, the default value is used.

Ref parameters:

static void Example(ref int value)
{
    Console.WriteLine("Value is {0}", value);
    value = 99;
}

usage
{
    int value = 10;
    Example(ref value); // Will print <Value is 10>
    Console.WriteLine("Value is {0}", value); // Will print <Value is 99>
}

Summary: If you pass a value type in as a ref (reference) the value itself gets changed. Allreference types are passed in as ref by default. FYI, int is a primitive types so needs an explicit "ref".

out parameters:

static void Example(out int value)
{
    value = 99;
    Console.WriteLine("Value is {0}", value);
}

usage
{
    int value; // no need to init it
    Example(out value); // Will print <Value is 99>
    Console.WriteLine("Value is {0}", value); // Will print <Value is 99>
}

Summary: Out parameters are like return variables but passed in via the signature of the method. Most common example is TryParse where the method returns vital information and depending on that information the out parameter is either valid or not (valid if it is true).

Ruskin
  • 1,504
  • 13
  • 25
0

Ok, its a duplicate of the linked question in the comments but I'll try to explain it for you.

Undecorated Parameters

Case A: public void MyFunc(int x) { }

-or-

Case B: public void MyFunc(MyClass y) { }

In Case A, the parameter is a value type, and value types are, by default, passed as copies of the original value to the function. This doesn't mean you aren't allowed to modify the value, but the value will not be reflected back at the calling location. This is the same for all value types, the value is copied before it is passed to the function.

In Case B, the parameter is a reference type. These types are passed by default as they are. They are not copied, but you are not allowed to change the reference (by assigning a new or null value to the type). You can change the contents of the object (any property/field there-of) and it will be reflected back in the calling location.

The ref keyword

Case A: public void MyFunc(ref int x) { }

-or-

Case B: public void MyFunc(ref MyClass x) { }

In case A, you are telling the compiler that you want to pass the value by reference, which means the compiler will not copy the type, but passes a reference to that type. The function is allowed to change it.

In case B, you are telling the compiler that the function is allowed to change where the reference points to (you can create a new or set it to null and it will be reflected in the calling site.

The out keyword

Case A: public void MyFunc(out int x) { }

-or-

Case B: public void MyFunc(out MyClass x) { }

Here, you are basically defining additional return types for the function. Its the method parameter telling the caller to expect a result in the place of the x variable. This is the same for both. The caller should not expect, in any case, that any value that x was before, will be the same afterwards. In fact you can expect that it will not be the same, because the method is required to assign a new value to x before it is allowed to return.

out basically means you provide a place for a return value, for value types just use the default constructor and for reference types initialize the value to null before you pass it in.

Ron Beyer
  • 11,003
  • 1
  • 19
  • 37