tags:

views:

191

answers:

5

Possible Duplicate:
Whats the difference between the 'ref' and 'out' keywords?

What is the difference between ref and out? I am confused about when to use ref and out. So please explain how to use ref and out, and in which situations.

+1  A: 

what a better way to show you giving you an MSDN link ;)

from that link:

The difference between ref and out is subtle but important. Each parameter passing mode is designed to apply to a slightly different programming scenario. The important difference between out and ref parameters is the definite assignment rules used by each.

balexandre
+10  A: 
  • You use Ref when you pass an initialized parameter and you expect the method/function to modify it.
  • You use Out when you pass an un-initialized parameter and the method will have to initialize and fill that parameter (you get a warning or even error otherwise).

    bool IsUserValid(string username);

    void IsUserValid(string username, out bool valid);

The declarations above are roughly the same. It's easier to return the value, so in this case you will use the return type. But if your method also needs to return the birth date of the user you can't return both parameters in the return, you have to use out parameters to return one of them (or void the method and return both as out).

AlexDrenea
+1  A: 

One thing to watch out for is when (not) to use "ref" with reference-type parameters. The "ref" is for the reference itself, not for the contents of the object that the reference points to.

If you pass a reference "by value" (that is, without 'ref' or 'out'), you can't change the reference (so a "new" will not survive the call), you can however still change the values of the properties this reference points to (if the class allows so).

Hans Kesting
+1  A: 

It's generally frowned upon to use (or abuse) out and ref, often it's much cleaner to return a struct or simple class, containing the multiple fields you need to "return".

As for ref vs. out, out requires an un-initialized variable, and the code will not compile unless you set the out param before exiting the function.

The code below will therefore not compile:

bool TryParse(string text, out int result)
{
  if (text == null)
    return false;
  else
  {
     // do the parsing
  }
}

ref's does not require you to set them. Also as Hans mentions you can actually "new" the object of a reference type when using ref (since you get a reference to the reference, which is roughly equal to a object** pointer in C++)

Steffen
A: 

Really there are 3 ways to pass a parameter to a method: by reference, by value and as output.

By value is the default and doesn't have a keyword in C# (it does in VB.Net: ByVal) - it passes a copy of value types:

public void SomeMethod1(int num) 
{
    num = 2;
}

int myNum = 1;
SomeMethod1( myNum  );
// myNum is still 1, we just set a new one

Confusingly - By value passes a copy of the reference for reference types. That means that your changes to a reference type point back to the instance, but you only have a copy of the actual pointer to the reference:

public void SomeMethod1(MyClass instance) 
{
    // changes the name on the instance
    instance.Name = "test 1";

    // we're only nulling the copy passed to this method
    instance = null;
}

public void SomeMethod2(MyClass instance) 
{
    // changes the name on the instance
    instance.Name = "test 2";

    // this is a new instance only in this method
    instance = new MyClass { Name = "new instance" };
}

MyClass myInst = new MyClass { Name = "original" };
SomeMethod1( myInst );
// myInst.Name is now "test 1"

SomeMethod2( myInst );
// myInst.Name is now "test 2"

Ok, so now by reference (ref in C# or ByRef in VB.Net) passes a reference to the value for structs:

public void SomeMethod1(ref int num) 
{
    num = 2;
}

int myNum = 1;
SomeMethod1( ref myNum  );
// myNum is now 2, we changed the reference

Simple enough, but for reference types by reference passes the actual pointer to the instance, not a copy:

public void SomeMethod1(ref MyClass instance) 
{
    // changes the name on the instance
    instance.Name = "test 1";

    // we're nulling the reference passed to this method
    instance = null;
}

public void SomeMethod2(ref MyClass instance) 
{
    // changes the name on the instance
    instance.Name = "test 2";

    // this is a new instance replacing the original
    instance = new MyClass { Name = "new instance" };
}

MyClass myInst = new MyClass { Name = "original" };
SomeMethod1( ref myInst );
// myInst.Name will now throw a NullReferenceException because myInst is null

SomeMethod2( ref myInst );
// myInst.Name is now "new instance"

So while both by reference and by value are similar for reference types, the behaviour is very distinct if you are changing the reference itself (rather than what you're referring to).

Finally as output is an extra return variable, just like the actual return. These two are bascially the same:

public int SomeMethod1() 
{
    return 1;
}

public void SomeMethod2(out int num) 
{
    num = 1;
}

If you have an out parameter it must be populated by the method (just like a return).

Keith