Someone asked me the other day when they should use the parameter keyword out
instead of ref
. While I (I think) understand the difference between the ref
and out
keywords (that has been asked before) and the best explanation seems to be that ref
== in
and out
, what are some (hypothetical or code) examples where I should always use out
and not ref
.
Since ref
is more general, why do you ever want to use out
? Is it just syntactic sugar?
You need to use
ref
if you plan to read and write to the parameter. You need to useout
if you only plan to write. In effect,out
is for when you'd need more than one return value, or when you don't want to use the normal return mechanism for output (but this should be rare).There are language mechanics that assist these use cases.
Ref
parameters must have been initialized before they are passed to a method (putting emphasis on the fact that they are read-write), andout
parameters cannot be read before they are assigned a value, and are guaranteed to have been written to at the end of the method (putting emphasis on the fact that they are write only). Contravening to these principles results in a compile-time error.For instance,
int.TryParse
returns abool
and accepts anout int
parameter:This is a clear example of a situation where you need to output two values: the numeric result and whether the conversion was successful or not. The authors of the CLR decided to opt for
out
here since they don't care about what theint
could have been before.For
ref
, you can look atInterlocked.Increment
:Interlocked.Increment
atomically increments the value ofx
. Since you need to readx
to increment it, this is a situation whereref
is more appropriate. You totally care about whatx
was before it was passed toIncrement
.In the next version of C#, it will even be possible to declare variable in
out
parameters, adding even more emphasis on their output-only nature:out
is more constraint version ofref
.In a method body, you need to assign to all
out
parameters before leaving the method. Also an values assigned to anout
parameter is ignored, whereasref
requires them to be assigned.So
out
allows you to do:where
ref
would require a and b to be assigned.Below are some notes which i pulled from this codeproject article on C# Out Vs Ref
If you are a visual person then please see this yourtube video which demonstrates the difference practically https://www.youtube.com/watch?v=lYdcY5zulXA
Below image shows the differences more visually
It depends on the compile context (See Example below).
out
andref
both denote variable passing by reference, yetref
requires the variable to be initialized before being passed, which can be an important difference in the context of Marshaling (Interop: UmanagedToManagedTransition or vice versa)MSDN warns:
Do not confuse the concept of passing by reference with the concept of reference types. The two concepts are not the same. A method parameter can be modified by ref regardless of whether it is a value type or a reference type. There is no boxing of a value type when it is passed by reference.
From the official MSDN Docs:
out
:The out keyword causes arguments to be passed by reference. This is similar to the ref keyword, except that ref requires that the variable be initialized before being passed
ref
:The ref keyword causes an argument to be passed by reference, not by value. The effect of passing by reference is that any change to the parameter in the method is reflected in the underlying argument variable in the calling method. The value of a reference parameter is always the same as the value of the underlying argument variable.
We can verify that the out and ref are indeed the same when the argument gets assigned:
CIL Example:
Consider the following example
in CIL, the instructions of
myfuncOut
andmyfuncRef
are identical as expected.nop: no operation, ldloc: load local, stloc: stack local, ldarg: load argument, bs.s: branch to target....
(See: List of CIL instructions )
Just to clarify on OP's comment that the use on ref and out is a "reference to a value type or struct declared outside the method", which has already been established in incorrect.
Consider the use of ref on a StringBuilder, which is a reference type:
As apposed to this:
How it sounds:
out = only initialize/fill a parameter (the parameter must be empty) return it out plain
ref = reference, standard parameter (maybe with value), but the function can modifiy it.