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