C# Language ref, out


Example

The ref and out keywords cause an argument to be passed by reference, not by value. For value types, this means that the value of the variable can be changed by the callee.

int x = 5;
ChangeX(ref x);
// The value of x could be different now

For reference types, the instance in the variable can not only be modified (as is the case without ref), but it can also be replaced altogether:

Address a = new Address();
ChangeFieldInAddress(a);
// a will be the same instance as before, even if it is modified
CreateANewInstance(ref a);
// a could be an entirely new instance now

The main difference between the out and ref keyword is that ref requires the variable to be initialized by the caller, while out passes that responsibility to the callee.

To use an out parameter, both the method definition and the calling method must explicitly use the out keyword.

int number = 1;
Console.WriteLine("Before AddByRef: " + number); // number = 1
AddOneByRef(ref number);
Console.WriteLine("After AddByRef: " + number);  // number = 2
SetByOut(out number);
Console.WriteLine("After SetByOut: " + number);  // number = 34

void AddOneByRef(ref int value)
{
    value++;
}

void SetByOut(out int value)
{
    value = 34;
}

Live Demo on .NET Fiddle

The following does not compile, because out parameters must have a value assigned before the method returns (it would compile using ref instead):

void PrintByOut(out int value)
{
    Console.WriteLine("Hello!");
}

using out keyword as Generic Modifier

out keyword can also be used in generic type parameters when defining generic interfaces and delegates. In this case, the out keyword specifies that the type parameter is covariant.

Covariance enables you to use a more derived type than that specified by the generic parameter. This allows for implicit conversion of classes that implement variant interfaces and implicit conversion of delegate types. Covariance and contravariance are supported for reference types, but they are not supported for value types. - MSDN

//if we have an interface like this
interface ICovariant<out R> { }

//and two variables like
ICovariant<Object> iobj = new Sample<Object>();
ICovariant<String> istr = new Sample<String>();

// then the following statement is valid
// without the out keyword this would have thrown error
iobj = istr; // implicit conversion occurs here