c# why What's the difference between the 'ref' and 'out' keywords?




why use out keyword in c# (20)

I'm creating a function where I need to pass an object so that it can be modified by the function. What is the difference between:

public void myFunction(ref MyClass someClass)

and

public void myFunction(out MyClass someClass)

Which should I use and why?


"Baker"

That's because the first one changes your string-reference to point to "Baker". Changing the reference is possible because you passed it via the ref keyword (=> a reference to a reference to a string). The Second call gets a copy of the reference to the string.

string looks some kind of special at first. But string is just a reference class and if you define

string s = "Able";

then s is a reference to a string class that contains the text "Able"! Another assignment to the same variable via

s = "Baker";

does not change the original string but just creates a new instance and let s point to that instance!

You can try it with the following little code example:

string s = "Able";
string s2 = s;
s = "Baker";
Console.WriteLine(s2);

What do you expect? What you will get is still "Able" because you just set the reference in s to another instance while s2 points to the original instance.

EDIT: string is also immutable which means there is simply no method or property that modifies an existing string instance (you can try to find one in the docs but you won't fins any :-) ). All string manipulation methods return a new string instance! (That's why you often get a better performance when using the StringBuilder class)


Mind well that the reference parameter which is passed inside the function is directly worked on.

For example,

    public class MyClass
    {
        public string Name { get; set; }
    }

    public void Foo()
    {
        MyClass myObject = new MyClass();
        myObject.Name = "Dog";
        Bar(myObject);
        Console.WriteLine(myObject.Name); // Writes "Dog".
    }

    public void Bar(MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

This will write Dog, not Cat. Hence you should directly work on someObject.


For those that learn by example (like me) here's what Anthony Kolesov is saying.

I've created some minimal examples of ref, out, and others to illustrate the point. I'm not covering best practices, just examples to understand the differences.

https://gist.github.com/2upmedia/6d98a57b68d849ee7091


ref and out behave similarly except following differences.

  • ref variable must be initialized before use. out variable can be used without assignment
  • out parameter must be treated as an unassigned value by the function that uses it. So, we can use initialized out parameter in the calling code, but the value will be lost when the function executes.

Since you're passing in a reference type (a class) there is no need use ref because per default only a reference to the actual object is passed and therefore you always change the object behind the reference.

Example:

public void Foo()
{
    MyClass myObject = new MyClass();
    myObject.Name = "Dog";
    Bar(myObject);
    Console.WriteLine(myObject.Name); // Writes "Cat".
}

public void Bar(MyClass someObject)
{
    someObject.Name = "Cat";
}

As long you pass in a class you don't have to use ref if you want to change the object inside your method.


ref tells the compiler that the object is initialized before entering the function, while out tells the compiler that the object will be initialized inside the function.

So while ref is two-ways, out is out-only.


I am going to try my hand at an explanation:

I think we understand how the value types work right? Value types are (int, long, struct etc.). When you send them in to a function without a ref command it COPIES the data. Anything you do to that data in the function only affects the copy, not the original. The ref command sends the ACTUAL data and any changes will affect the data outside the function.

Ok on to the confusing part, reference types:

Lets create a reference type:

List<string> someobject = new List<string>()

When you new up someobject, two parts are created:

  1. The block of memory that holds data for someobject.
  2. A reference (pointer) to that block of data.

Now when you send in someobject into a method without ref it COPIES the reference pointer, NOT the data. So you now have this:

(outside method) reference1 => someobject
(inside method)  reference2 => someobject

Two references pointing to the same object. If you modify a property on someobject using reference2 it will affect the same data pointed to by reference1.

 (inside method)  reference2.Add("SomeString");
 (outside method) reference1[0] == "SomeString"   //this is true

If you null out reference2 or point it to new data it will not affect reference1 nor the data reference1 points to.

(inside method) reference2 = new List<string>();
(outside method) reference1 != null; reference1[0] == "SomeString" //this is true

The references are now pointing like this:
reference2 => new List<string>()
reference1 => someobject

Now what happens when you send someobject by ref to a method? The actual reference to someobject gets sent to the method. So you now have only one reference to the data:

(outside method) reference1 => someobject;
(inside method)  reference1 => someobject;

But what does this mean? It acts exactly the same as sending someobject not by ref except for two main thing:

1) When you null out the reference inside the method it will null the one outside the method.

 (inside method)  reference1 = null;
 (outside method) reference1 == null;  //true

2) You can now point the reference to a completely different data location and the reference outside the function will now point to the new data location.

 (inside method)  reference1 = new List<string>();
 (outside method) reference1.Count == 0; //this is true

I may not be so good at this, but surely strings (even though they are technically reference types and live on the heap) are passed by value, not reference?

        string a = "Hello";

        string b = "goodbye";

        b = a; //attempt to make b point to a, won't work.

        a = "testing";

        Console.WriteLine(b); //this will produce "hello", NOT "testing"!!!!

This why you need ref if you want changes to exist outside of the scope of the function making them, you aren't passing a reference otherwise.

As far as I am aware you only need ref for structs/value types and string itself, as string is a reference type that pretends it is but is not a value type.

I could be completely wrong here though, I am new.


They're pretty much the same - the only difference is that a variable you pass as an out parameter doesn't need to be initialised, and the method using the ref parameter has to set it to something.

int x;    Foo(out x); // OK 
int y;    Foo(ref y); // Error

Ref parameters are for data that might be modified, out parameters are for data that's an additional output for the function (eg int.TryParse) that are already using the return value for something.


Authoring Time:

(1) We create the calling method Main()

(2) it creates a List object (which is a reference type object) and stores it in the variable myList.

public sealed class Program 
{
    public static Main() 
    {
        List<int> myList = new List<int>();

During Runtime:

(3) Runtime allocates a memory on stack at #00, wide enough to store an address (#00 = myList, since variable names are really just aliases for memory locations)

(4) Runtime creates a list object on heap at memory location #FF( all these addresses are for example sakes)

(5) Runtime would then store the starting address #FF of the object at #00(or in words, stores the reference of the List object in the pointer myList)

Back to Authoring Time:

(6) We then pass the List object as argument myParamList to the called method modifyMyList and assign a new List object to it

List<int> myList = new List<int>();

List<int> newList = ModifyMyList(myList)

public List<int> ModifyMyList(List<int> myParamList){
     myParamList = new List<int>();
     return myParamList;
}

During Runtime:

(7) Runtime starts the call routine for the called method and as part of it, checks the type of parameters.

(8) Upon finding the reference type, it allocates a memory on stack at #04 for aliasing the parameter variable myParamList.

(9) It then stores the value #FF in it as well.

(10) Runtime creates a list object on heap at memory location #004 and replaces #FF in #04 with this value(or dereferenced the original List object and pointed to the new List object in this method)

The address in #00 is not altered and retains the reference to #FF(or the original myList pointer is not disturbed).


The ref keyword is a compiler directive to skip the generation of runtime code for (8) and (9) which means there will be no heap allocation for method parameters. It will use the original #00 pointer to operate on the object at #FF. If the original pointer is not initialised, the runtime will halt complaining it can’t proceed since the variable isn’t initialised

The out keyword is a compiler directive which pretty much is the same as ref with a slight modification at (9) and (10). The compiler expects the argument to be uninitialised and will continue with (8), (4) and (5) to create an object on heap and to stores its starting address in the argument variable. No uninitialised error will be thrown and any previous reference stored will be lost.


Out: A return statement can be used for returning only one value from a function. However, using output parameters, you can return two values from a function. Output parameters are like reference parameters, except that they transfer data out of the method rather than into it.

The following example illustrates this:

using System;

namespace CalculatorApplication
{
   class NumberManipulator
   {
      public void getValue(out int x )
      {
         int temp = 5;
         x = temp;
      }

      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* local variable definition */
         int a = 100;

         Console.WriteLine("Before method call, value of a : {0}", a);

         /* calling a function to get the value */
         n.getValue(out a);

         Console.WriteLine("After method call, value of a : {0}", a);
         Console.ReadLine();

      }
   }
}

ref: A reference parameter is a reference to a memory location of a variable. When you pass parameters by reference, unlike value parameters, a new storage location is not created for these parameters. The reference parameters represent the same memory location as the actual parameters that are supplied to the method.

In C#, you declare the reference parameters using the ref keyword. The following example demonstrates this:

using System;
namespace CalculatorApplication
{
   class NumberManipulator
   {
      public void swap(ref int x, ref int y)
      {
         int temp;

         temp = x; /* save the value of x */
         x = y;   /* put y into x */
         y = temp; /* put temp into y */
       }

      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* local variable definition */
         int a = 100;
         int b = 200;

         Console.WriteLine("Before swap, value of a : {0}", a);
         Console.WriteLine("Before swap, value of b : {0}", b);

         /* calling a function to swap the values */
         n.swap(ref a, ref b);

         Console.WriteLine("After swap, value of a : {0}", a);
         Console.WriteLine("After swap, value of b : {0}", b);

         Console.ReadLine();

      }
   }
}

Let's say Dom shows up at Peter's cubicle about the memo about the TPS reports.

If Dom were a ref argument, he would have a printed copy of the memo.

If Dom were an out argument, he'd make Peter print a new copy of the memo for him to take with him.


ref and out work just like passing by references and passing by pointers as in C++.

For ref, the argument must declared and initialized.

For out, the argument must declared but may or may not be initialized

        double nbr = 6; // if not initialized we get error
        double dd = doit.square(ref nbr);

        double Half_nbr ; // fine as passed by out, but inside the calling  method you initialize it
        doit.math_routines(nbr, out Half_nbr);

Extending the Dog, Cat example. The second method with ref changes the object referenced by the caller. Hence "Cat" !!!

    public static void Foo()
    {
        MyClass myObject = new MyClass();
        myObject.Name = "Dog";
        Bar(myObject);
        Console.WriteLine(myObject.Name); // Writes "Dog". 
        Bar(ref myObject);
        Console.WriteLine(myObject.Name); // Writes "Cat". 
    }

    public static void Bar(MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

    public static void Bar(ref MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

I was playing with the ref and found this example quite interesting. I thought the call of RefEater(ref s1); will cause build error as in the second commented case, but the s1 field is initialized to its default value before the constructor is called (https://.com/a/1920659/5612780).

public class Class1
{
    // this will have the default value
    private string s1;

    public Class1()
    {
        // no issue here..
        RefEater(ref s1);

        // Error CS0165 Use of unassigned local variable 's2'
        //string s2;
        //RefEater(ref s2);
    }

    private void RefEater(ref string s)
    {

    }
}

If you want to pass your parameter as a ref then you should initialize it before passing parameter to the function else compiler itself will show the error.But in case of out parameter you don't need to initialize the object parameter before passing it to the method.You can initialize the object in the calling method itself.


The ref modifier means that:

  1. The value is already set and
  2. The method can read and modify it.

The out modifier means that:

  1. The Value isn't set and can't be read by the method until it is set.
  2. The method must set it before returning.

ref is in and out.

You should use out in preference wherever it suffices for your requirements.


out:

In C#, a method can return only one value. If you like to return more than one value, you can use the out keyword. The out modifier return as return-by-reference. The simplest answer is that the keyword “out” is used to get the value from the method.

  1. You don't need to initialize the value in the calling function.
  2. You must assign the value in the called function, otherwise the compiler will report an error.

ref:

In C#, when you pass a value type such as int, float, double etc. as an argument to the method parameter, it is passed by value. Therefore, if you modify the parameter value, it does not affect argument in the method call. But if you mark the parameter with “ref” keyword, it will reflect in the actual variable.

  1. You need to initialize the variable before you call the function.
  2. It’s not mandatory to assign any value to the ref parameter in the method. If you don’t change the value, what is the need to mark it as “ref”?

 public static void Main(string[] args)
    {
        //int a=10;
        //change(ref a);
        //Console.WriteLine(a);
        // Console.Read();

        int b;
        change2(out b);
        Console.WriteLine(b);
        Console.Read();
    }
    // static void change(ref int a)
    //{
    //    a = 20;
    //}

     static void change2(out int b)
     {
         b = 20;
     }

you can check this code it will describe you its complete differnce when you use "ref" its mean that u already initialize that int/string

but when you use "out" it works in both conditions wheather u initialize that int/string or not but u must initialize that int/string in that function







ref