When to pass ref keyword in

后端 未结 6 924
野性不改
野性不改 2020-12-06 11:45

I\'ve read the difference between passng and not passing ref in parameters, however, when would I want to use them?

For example, I had some logic in a method which c

相关标签:
6条回答
  • 2020-12-06 12:24

    The effect is that any changes to the parameter in the method will be reflected in that variable when control passes back to the calling method. So if you want the value assigned to the parameter to survive past the method call it's a possible usecase

    0 讨论(0)
  • 2020-12-06 12:25

    Conceptually, the difference is that a value type stores its value directly, whereas a reference type stores a reference to the value. Maybe you should re-read a bit about reference vs value types.

    Passing value types by reference--as demonstrated above--is useful, but ref is also useful for passing reference types. This allows called methods to modify the object to which the reference refers because the reference itself is being passed by reference. The following sample shows that when a reference type is passed as a ref parameter, the object itself can be changed.

       class RefRefExample
    {
        static void Method(ref string s)
        {
            s = "changed";
        }
        static void Main()
        {
            string str = "original";
            Method(ref str);
            // str is now "changed"
        }
    } 
    

    MSDN

    0 讨论(0)
  • 2020-12-06 12:35

    Let me break that down into two questions:

    1) When should one use ref/out formal parameter declarations when writing a method?

    Use ref/out when you desire your method to be able to read and write a variable passed in from the caller, rather than merely reading a value.

    2) Why does an "extract method" refactoring produce a ref parameter?

    I don't know the details of Resharper, but I can make a guess. Consider the following evil mutable value type:

    struct S 
    { 
      private int x;
      public int X() { return this.x; } 
      public void M() { this.x += 1; } 
    }
    

    You have a method:

    void Foo() 
    {
        S s = new S();
        Fred(s);
        Blah(s);
        Bar(s);
        s.M();
        Console.WriteLine(s.X()); // prints 1
    }
    

    and you do "extract method" on the middle bit:

    void NewMethod(ref S s)
    {
        Blah(s);
        Bar(s);
        s.M();
    }
    
    void Foo() 
    {
        S s = new S();
        Fred(s);
        NewMethod(ref s);
        Console.WriteLine(s.X()); // still prints 1
    }
    

    If instead you made a method without "ref" then calling NewMethod(s) would pass a copy of s to NewMethod. Remember, value types are copied by value; that's why we called them "value types". It would be the copy that gets mutated, and then s.X() returns zero. It is a bad idea for a refactoring to introduce a semantic change in a program, and it is difficult for a refactoring engine to know whether a given method relies on the mutability of a value type or not.

    This is just another reason why you should avoid mutable value types.

    0 讨论(0)
  • 2020-12-06 12:39

    Consider this example:

    static int i = 3;
    
    public static void ChangeIntRef(ref int val)
    {
       val = 5;
    }
    
    public static void ChangeInt(int val)
    {
       val = 5;
    }
    
    Console.WriteLine(i);
    ChangeInt(i);
    Console.WriteLine(i);
    
    ChangeIntRef(ref i);
    Console.WriteLine(i);
    

    By passing the parameter as ref, you are telling the compiler that what you actually want is a reference to the original variable to be passed to the method. As a result, the method can change the value of the original variable.

    If you run the snippet from above, the result is:

    3
    3
    5
    

    This should clearly show that without the ref keyword, the ChangeInt method is not able to actually change the original value. However, with the ref keyword the ChangeIntRef method is able to change the original value.

    0 讨论(0)
  • 2020-12-06 12:45

    I use references for semantics. Consider this approach:

    void AddResultsTable(ref PlaceHolder p) // modifies p; adding a table
    {
        var t = new Table();
    
        AddTableHeader(ref t); // modifies t; adding a table header
    
        AddTableBody(ref t);  // modifies t; adding a table body
    
        AddTableFooter(ref t);  // modifies t; adding a table footer
    
        p.Controls.Add(t);
    }
    
    AddResultsTable(ref PlaceHolderResults);
    

    Versus this one:

    Table ReturnTable()
    {
        var t new Table();
    
        // AddTableHeader() returns TableHeader
        t.Columns.HeaderColumns.Add(ReturnTableHeader());
    
        // ... etc.
    
        return t;
    }
    
    PlaceHolder.Controls.Add(ReturnTable());
    

    The first snippet of code looks cleaner to me; methods modifies objects rather than returning new object(s) which you in turn have to add. It all stays "boxed in" and hidden, inside the methods.

    0 讨论(0)
  • 2020-12-06 12:48

    Passing byref makes sense only for "side effects" of a function: i.e., you intend to modify a value-type parameter, or reassign another object to a given object parameter, and have that change survive the function call. Example: TryGetValue().

    Otherwise, best to stick with byval.

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