Coder Perfect

When sending an object, why use the’ref’ keyword?

Problem

Why should I use the ref keyword when giving an object to a method? Isn’t this, after all, the default behavior?

For example:

class Program
{
    static void Main(string[] args)
    {
        TestRef t = new TestRef();
        t.Something = "Foo";

        DoSomething(t);
        Console.WriteLine(t.Something);
    }

    static public void DoSomething(TestRef t)
    {
        t.Something = "Bar";
    }
}


public class TestRef
{
    public string Something { get; set; }
}

“Bar” is the output, indicating that the item was supplied as a reference.

Asked by Ryan

Solution #1

If you want to update the object, pass a ref:

TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(ref t);

void DoSomething(ref TestRef t)
{
  t = new TestRef();
  t.Something = "Not just a changed t, but a completely different TestRef object";
}

T does not refer to the initial new TestRef after invoking DoSomething; instead, it refers to a whole separate object.

If you want to change the value of an immutable object, such as a string, this may also be handy. A string’s value cannot be changed once it has been formed. However, by utilizing a ref, you may write a function that swaps out the string for one with a different value.

Using ref unless absolutely necessary is not a smart idea. Because ref allows the method to alter the argument to something else, callers of the method must be written to account for this possibility.

Object variables always behave as references to the object when the parameter type is an object. This means that when you use the ref keyword, you’re referring to a reference. This enables you to carry out the actions outlined in the preceding example. However, if the parameter type is a primitive value (such as int), the value of the argument handed in will be modified once the procedure returns:

int x = 1;
Change(ref x);
Debug.Assert(x == 5);
WillNotChange(x);
Debug.Assert(x == 5); // Note: x doesn't become 10

void Change(ref int x)
{
  x = 5;
}

void WillNotChange(int x)
{
  x = 10;
}

Answered by Scott Langham

Solution #2

You need to distinguish between “passing a reference by value”, and “passing a parameter/argument by reference”.

To avoid having to write carefully each time this comes up in newsgroups, I’ve created a somewhat substantial article on the subject.

Answered by Jon Skeet

Solution #3

When you send any parameter to a method in.NET, it creates a copy. In value types, any changes you make to the value are made within the method scope and are lost when you depart the method.

When passing a Reference Type, a copy is also made, but it is a copy of a reference, i.e. now you have TWO references in memory to the same object. As a result, if you use the reference to change the object, it will be changed. But if you modify the reference itself – we must remember it is a copy – then any changes are also lost upon exiting the method.

An assignment, as previously stated, is a modification of the reference, and hence is lost:

public void Method1(object obj) {   
 obj = new Object(); 
}

public void Method2(object obj) {  
 obj = _privateObject; 
}

The techniques shown above do not change the original object in any way.

A minor alteration to your example

 using System;

    class Program
        {
            static void Main(string[] args)
            {
                TestRef t = new TestRef();
                t.Something = "Foo";

                DoSomething(t);
                Console.WriteLine(t.Something);

            }

            static public void DoSomething(TestRef t)
            {
                t = new TestRef();
                t.Something = "Bar";
            }
        }



    public class TestRef
    {
    private string s;
        public string Something 
        { 
            get {return s;} 
            set { s = value; }
        }
    }

Answered by Ricardo Amores

Solution #4

You can alter the contents of t without giving it as a ref because TestRef is a class (which are reference objects). TestRef, on the other hand, can change what the original t refers to if you pass it as a ref. Make it point to a different item, for example.

Answered by Ferruccio

Solution #5

You may use ref to write:

static public void DoSomething(ref TestRef t)
{
    t = new TestRef();
}

And after the technique is finished, t will be altered.

Answered by Rinat Abdullin

Post is based on https://stackoverflow.com/questions/186891/why-use-the-ref-keyword-when-passing-an-object