In depth analysis of the differences between ref and out

  • 2020-05-17 06:18:45
  • OfStack

Both ref and out are keywords in C# and do the same thing, specifying that one parameter is passed by reference.
For a compiled program, there is no difference between them, that is, there are only syntactic differences.
In summary, they have the following grammatical differences:

1. The parameters passed by ref must be initialized before the call, out does not, that is:


int i;
SomeMethod( ref i );// Grammar mistakes 
SomeMethod( out i );// through 

2. The parameters passed by ref can be directly used inside the function, while out cannot:

public void SomeMethod(ref int i)
{
   int j=i;// through 
   //...
}
public void SomeMethod(out int i)
{
   int j=i;// Grammar mistakes 
}

3. Parameters passed by ref can not be modified inside the function, but out must be assigned before leaving the body of the function.
ref must be initialized before parameters are passed; out, on the other hand, does not have to be initialized before it is passed, and The conversion process between a value type and a reference type is called boxing and unboxing.

Conclusion:
It should be said that the system has fewer restrictions on ref. Although out does not require 1 to be initialized before the call, its value is not visible inside the function, that is, it cannot use the value passed in through out, and 1 must be assigned a value inside the function. Or the function takes responsibility for initializing the variable.

Here's what the difference is between ref and out:
1. About overloading
Principle: methods with the out|ref keyword can be overloaded with methods without the out and ref keywords. However, if you want to overload between out and ref, the compiler will prompt you that you cannot define method overloading only on ref and out

2 about the initial value before the call
Principle: arguments must have an initial value before a function that takes ref as a parameter can be called. Otherwise, the compiler will prompt that an unassigned local variable is used.
Arguments can be uninitialized before a function that takes out as an argument is called.

3 about the initial value problem of parameters introduced in the function: in the function being called, the parameters introduced by out are assigned at least once before returning, otherwise the compiler will prompt that an unassigned out parameter is used;
Within the called function, parameters introduced by ref do not have to be assigned initial values before they are returned.

Summary: ref and out in C# provide a solution for passing value types by reference. Of course, reference types can also be modified with ref and out, but that no longer makes sense. Because the reference data type is essentially a copy of the passed reference itself rather than a value. The ref and out keywords will tell the compiler that the address of the parameter is being passed instead of the parameter itself, just as the reference type is passed by default. At the same time, the compiler does not allow overloading between out and ref, which fully shows that the difference between out and ref is only from the perspective of the compiler, and the IL code generated by them is 1 sample. One might wonder, as I did when I first learned it, why you can pass value types by address when they don't allocate memory in the managed heap. Value type while living in the thread's stack, it itself is representative of the data itself (and different from the reference data type itself but does not represent the data points to a memory reference), but the value type has its own address, that is a pointer, and now with ref out after modification, the transfer is the pointer, so can realize the modified a, b the value of the real exchange. That's what ref and out do for us.

First: both are passed by address and will change the value of the original parameter after use.
Second: rel can pass the value of the parameter into the function, but out wants to empty the parameter, that is, you can't pass a value from out. After out enters, the value of the parameter is empty, so you must initialize it once. This is the difference between the two, or as some netizens say, rel is in and out, out is in and out.

ref (C# reference)
The ref keyword causes the parameter to be passed by reference. The effect is that when control is passed back to the calling method, any changes to the parameters in the method are reflected in the variable. To use the ref parameter, both the method definition and the method invocation must explicitly use the ref keyword.
Such as:


class RefExample
{
    static void Method(ref int i)
    {
        i = 44;
    }
    static void Main()
    {
        int val = 0;
        Method(ref val);
        // val is now 44
    }
}

The parameters passed to the ref parameter must be initialized first. This is different from out, whose parameters do not need to be explicitly initialized before they are passed.
Although ref and out are handled differently at run time, they are handled the same at compile time. Therefore, if one method takes the ref parameter and the other takes the out parameter, you cannot overload the two methods. For example, from a compilation perspective, the two methods in the following code are identical, so the following code will not be compiled:

class CS0663_Example 
{
    // Compiler error CS0663: "cannot define overloaded 
    // methods that differ only on ref and out".
    public void SampleMethod(ref int i) { }
    public void SampleMethod(out int i) { }
}

However, if one method takes the ref or out parameters and the other method does not, you can overload it, as shown in the following example:

class RefOutOverloadExample
{
    public void SampleMethod(int i) { }
    public void SampleMethod(ref int i) { }
}

out (C# reference)
The out keyword causes the parameter to be passed by reference. This is similar to the ref keyword, except that ref requires that the variable be initialized before it is passed. To use the out parameter, both the method definition and the method invocation must explicitly use the out keyword.
Such as:

class OutExample
{
    static void Method(out int i)
    {
        i = 44;
    }
    static void Main()
    {
        int value;
        Method(out value);
        // value is now 44
    }
}

Although a variable passed as an out parameter does not have to be initialized before it is passed, a method needs to be called to assign a value before the method returns.

The ref and out keywords are handled differently at run time, but the same at compile time. Therefore, if one method takes the ref parameter and the other takes the out parameter, the two methods cannot be overloaded. For example, from a compilation perspective, the two methods in the following code are identical, so the following code will not be compiled:

class CS0663_Example 
{
    // Compiler error CS0663: "Cannot define overloaded 
    // methods that differ only on ref and out".
    public void SampleMethod(out int i) { }
    public void SampleMethod(ref int i) { }
} 

However, if one method takes the ref or out arguments, and the other method does not, it can be overloaded,
As follows:

class RefOutOverloadExample
{
    public void SampleMethod(int i) { }
    public void SampleMethod(out int i) { }
}


Related articles: