tags:

views:

958

answers:

9

Hi

If I am passing an object to a method, why should I use the ref keyword? Isn't this the default behaviour anyway?

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; }
    }

The output is "Bar" which means that the object was passed as a reference.

A: 

If you're passing a value, however, things are different. You can force a value to be passed by reference. This allows you to pass an integer to a method, for example, and have the method modify the integer on your behalf.

Andrew
Whether you're passing a reference or a value type value, the default behaviour is to pass by value. You just need to understand that with reference types, the value you're passing *is* a reference. This isn't the same as passing *by* reference.
Jon Skeet
+1  A: 

with ref you can write:

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

and t will be changed after the method has completed.

Rinat Abdullin
+14  A: 

Pass a ref if you want to change what the object is:

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";
}

After calling DoSomething, t does not refer to the original 'new TestRef', but refers to a completely different object.

This may be useful too if you want to change the value of an immutable object, eg a string. You can't change the value of a string once it has been created, but by using a ref, you could create a function that changes the string for another one that has a different value.

Edit: As other people have mention. It is not a good idea to use ref unless it is needed. Using ref gives the method freedom to change the argument for something else, callers of the method will need to to be coded to ensure they handle this possibility.

Also. When the parameter type is an object, then object variables always act as references to the object. This means, when the ref keyword is used you've got a reference to a reference. This allows you to do things as described in the example given above. But, when the parameter type is a primitive value (eg int), then if this parameter is assigned to within the method, the value of the argument that was passed in will be changed after the method 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;
}
Scott Langham
"change the value of a mutable object" - you mean immutable.
Jon Skeet
Yes, thanks Jon, I'll fix that.
Scott Langham
+1  A: 

Since TestRef is a class (which are reference objects), you can change the contents inside t without passing it as a ref. However, if you pass t as a ref, TestRef can change what the original t refers to. i.e. make it point to a different object.

Ferruccio
A: 

By using the ref keyword with reference types you are effectively passing a reference to the reference. In many ways it's the same as using the out keyword but with the minor difference that there's no guarantee that the method will actually assign anything to the ref'ed parameter.

Isak Savo
why was this modded down? The explaination I gave is 100% accurate and relevant to the question
Isak Savo
A: 

This is like passing a pointer to a pointer in C. In .NET this will allow you to change what the original T refers to, personally though I think if you are doing that in .NET you have probably got a design issue!

pezi_pink_squirrel
A: 

Ref denotes whether the function can get its hands on the object itself, or only on its value.

Passing by reference is not bound to a language; it's a parameter binding strategy next to pass-by-value, pass by name, pass by need etc...

A sidenote: the class name TestRef is a hideously bad choice in this context ;).

xtofl
+2  A: 

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

I've written a reasonably long article on the subject to avoid having to write carefully each time this comes up on newsgroups :)

Jon Skeet
A: 

In .NET when you pass any parameter to a method, a copy is created. In value types means that any modification you make to the value is at the method scope, and is losed when you exit the method. When passing a Reference Type, a copy is also made, but is a copy of a reference, i.e. now you have TWO references in memory to the same object. So, if you use the reference to modify the object, it gets modified. But if you modify the reference itself -we must recall is a copy- then any changes are also loosed upon exiting the method.

As people have said before, an assignment is a modification of the reference, thus is loosed:

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

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

The methods above does not modifies the original object.

A little modification of 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; }
     }
    }
Ricky AH