A C# ref
parameter is passed as a reference, not a value. This means we can assign the parameter in the called method and have it also be assigned at the calling site.
There is a difference between ref
and out. Unlike with "out," we do not need to assign an initial value to ref
before passing it to a method.
This program defines the Program
class
with Main
and 2 other methods—SetString1
and SetString2
. The methods have formal parameter lists with ref
keywords.
ref
keyword. Whenever we pass a string
to this method, it must have the ref
keyword.SetString2
, we must use the out keyword on its argument.string
parameter before sending it to SetString2
.using System; class Program { static void Main() { // Part 1: use ref argument. string value1 = "cat"; SetString1(ref value1); Console.WriteLine(value1); // Part 2: use out argument. string value2; SetString2(1, out value2); Console.WriteLine(value2); } static void SetString1(ref string value) { if (value == "cat") { Console.WriteLine("Is cat"); } value = "dog"; } static void SetString2(int number, out string value) { if (number == 1) { value = "one"; } else { value = "carrot"; } } }Is cat dog one
We can refactor code that acts upon multiple local variables or fields. We create a method with a ref
argument. And then we pass each separate variable to this method.
ref
argument in the NullIf
method both reads and writes the string
. It is an input and output argument.using System; class Program { static void Main() { string v1 = "dot"; string v2 = "net"; string v3 = "perls"; NullIf(ref v1); NullIf(ref v2); NullIf(ref v3); Console.WriteLine(v1); Console.WriteLine(v2); Console.WriteLine(v3); } static void NullIf(ref string value) { if (value == "net") { value = null; } } }dot perls
A method can return a reference to an argument or a local. This is useful if we want to modify the returned object, and have these modifications reflected in the current scope.
HigherValue
method. It compares the structs, and returns a reference to one of them.HigherValue
. We modify the returned struct
.Main
method. So the ref
return affects the local state of Main
.using System; struct Test { public int Value; } class Program { static ref Test HigherValue(ref Test left, ref Test right) { // Compares the two Test struct arguments. // ... Return a reference to the one with the higher value. if (left.Value > right.Value) { return ref left; } else { return ref right; } } static void Main() { Test t1; t1.Value = 10; Test t2; t2.Value = 20; // Get the struct with the higher value. // ... Then modify its value. HigherValue(ref t1, ref t2).Value = 30; // Display values of 2 structs. Console.WriteLine(t1.Value); Console.WriteLine(t2.Value); } }10 30
To use a ref
return to our advantage, a mutable struct
(or array) is needed. We can assign to the result of a method—this effect is reflected in the current method.
The difference between ref
and out is in the C# language itself. In the intermediate language, we find that the ref
and out parameters are called with the "string
" type.
string
" type aliases the System.String
type in the base class library, so it is not special-cased here.Ref and out can confuse the overload resolution step in the C# compiler. For this reason, it is a bad idea to mix ref
and out parameters in an interface
or object method group.
Out is sometimes used in methods that enhance performance—it can lead to simpler code. But often it makes code more complex and should be avoided.
The ref
keyword allows us to pass variable references, as opposed to object references. The storage location of the variable itself is copied on the method invocations.