Using REF & OUT keywords with Passing by Reference & Passing by Value in C#

前端 未结 7 578
南笙
南笙 2021-01-12 06:32

Here is what I understand so far:

PASS BY VALUE

Passing by value means a copy of an argument is passed. Changes to that copy do not change the original.

相关标签:
7条回答
  • 2021-01-12 06:47

    You pass by ref something you want to be read and written by another function, so you should pass the variable initialized in order to be correctly read.

    EDIT: example:

    void mymethod(ref int a) {
      a++;
    }
    

    You pass as OUT something you want to be written by another function, but you don't need to initialize it as it won't be read by the function, only written.

    EDIT: example:

    void mymethod2(out string a) {
      a="hello";
    }
    
    0 讨论(0)
  • 2021-01-12 06:49

    Using the OUT keyword is useful if you have a method that you need to return more than one value. For example, look at methods like int.TryParse().

    Using REF is more for explicitness of objects. Keeping in mind that any non-primitive passed into a method is inherently passed by reference there's not a lot of need for it in normal managed code. By declaring the REF keyword you're stating that the parameter will likely be modified in the body of the method and thus the calling code should be aware of it (thus why you have to explicitly add the ref in the calling code as well.

    0 讨论(0)
  • 2021-01-12 06:50

    Edit: I have corrected this answer to reflect that the 'out' keyword in C# does not do what you might expect it to (eg a true OUT parameter in the computer science sense of the term). I originally stated that 'out' was pass by value OUT but was proven wrong.

    You can't use 'out' and 'ref' together. There are three calling conventions in C# (NET Framework):

    • No keyword = Pass by value (IN)
    • 'out' Keyword = Pass by reference (REF) with no definite assignment requirement before call
    • 'ref' Keyword = Pass by reference (REF) with a definite assignment requirement before call

    C# has no true OUT or IN-OUT parameter ability.

    To see that 'out' parameters in C# are not true OUT parameters, you can use the following code:

      public class Test
      {
        Action _showValue;
    
        public void Run()
        {
          string local = "Initial";
          _showValue = () => { Console.WriteLine(local.ToString()); };
    
          Console.WriteLine("Passing by value");
          inMethod(local);
    
          Console.WriteLine("Passing by reference with 'out' keyword");
          outMethod(out local);
    
          Console.WriteLine("Passing by reference with 'ref' keyword");
          refMethod(ref local);
    
        }
    
        void inMethod(string arg)
        {
          _showValue();
          arg = "IN";
          _showValue();
        }
    
        void outMethod(out string arg)
        {
          _showValue();
          arg = "OUT";
          _showValue();
        }
    
        void refMethod(ref string arg)
        {
          _showValue();
          arg = "REF";
          _showValue();
        }
      }
    

    The output is:

    Passing by value
    Initial
    Initial
    Passing by reference with 'out' keyword
    Initial
    OUT
    Passing by reference with 'ref' keyword
    OUT
    REF
    

    As you can see, both 'out' and 'ref' actually pass by REF. The only difference is in how the compiler treats them for definite assignment purposes.

    0 讨论(0)
  • 2021-01-12 06:51

    You would never combine ref and out on 1 parameter. They both mean 'pass by reference'.

    You can of course combine ref parameters and out parameters in one method.

    The difference between ref and out lies mainly in intent. ref signals 2-way data transport, out means 1-way.

    But besides intent, the C# compiler tracks definite-assignment and that makes the most noticable difference. It also prevents the misuse (reading) of an out parameter.

    void SetOne(out int x) 
    {
      int y = x + 1; // error, 'x' not definitely assigned.
      x = 1;         // mandatory to assign something
    }
    
    void AddTwo(ref int x)
    {
        x = x + 2;  // OK, x  is known to be assigned
    }
    
    void Main()
    {
        int foo, bar;
    
        SetOne(out foo); // OK, foo does not have to be assigned
        AddTwo(ref foo); // OK, foo assigned by SetOne
        AddTwo(ref bar); // error, bar is unassigned
    }
    
    0 讨论(0)
  • 2021-01-12 07:06

    If you understand c++ maybe this will help you:

    void Foo(Bar) {} // pass by value c# (if it's a value type ;))
    void Foo(Bar) {} // c++
    
    void Foo(Bar) {} // pass by reference c# (if it's a reference type ;))
    void Foo(Bar&) {} // c++
    
    void Foo(ref Bar) {} // c#
    void Foo(Bar*) // c++
    
    void Foo(out Bar) {} // c#
    void Foo(Bar**) {} // c++ (the contents of *Bar needs to be filled up)
    
    0 讨论(0)
  • 2021-01-12 07:07

    You understand the dynamics of passing either way. Some parameter scenarios might be:

    • ref int num for an in/out parameter. The function may modify the value in it.
    • out int num like ref except function must assign a value to it before returning.

    In general output parameters are good for when a function must return multiple values, because a function only has one return value (although it can be compound).

    Sometimes data access providers, like some ADO.NET methods, use output parameters to deliver information back. Some data access methods mimic database stored procedures which have in/out parameters.

    Edit: One stipulation for reference types is the parameters ref StringBuilder word or StringBuilder word (by value) behave the same - the string outside is affected, although the underlying implementatoin may differ slightly because at that point the focus is the reference and not the value on the heap.

    0 讨论(0)
提交回复
热议问题