When to use in vs ref vs out
You should use out
unless you need ref
.
It makes a big difference when the data needs to be marshalled e.g. to another process, which can be costly. So you want to avoid marshalling the initial value when the method doesn't make use of it.
Beyond that, it also shows the reader of the declaration or the call whether the initial value is relevant (and potentially preserved), or thrown away.
As a minor difference, an out parameter needs not be initialized.
Example for out
:
string a, b;
person.GetBothNames(out a, out b);
where GetBothNames is a method to retrieve two values atomically, the method won't change behavior whatever a and b are. If the call goes to a server in Hawaii, copying the initial values from here to Hawaii is a waste of bandwidth. A similar snippet using ref:
string a = String.Empty, b = String.Empty;
person.GetBothNames(ref a, ref b);
could confuse readers, because it looks like the initial values of a and b are relevant (though the method name would indicate they are not).
Example for ref
:
string name = textbox.Text;
bool didModify = validator.SuggestValidName(ref name);
Here the initial value is relevant to the method.
What's the difference between the 'ref' and 'out' keywords?
ref
tells the compiler that the object is initialized before entering the function, while out
tells the compiler that the object will be initialized inside the function.
So while ref
is two-ways, out
is out-only.
Keywords `in, out, ref` vs Attributes `[In], [Out], [In, Out]`
They are not equivalent.
For the ref int[] arr
the default [In, Out]
attributes will be applied automatically, but it is still not the same as [In, Out] int[] arr
.
ref int[] arr
is a double indirection (a reference type passed by reference). Use this if the native side is defined something like this: int32_t** arr
. This allows to replace not just the elements but the whole array instance as well.
On the other hand, [In, Out] int[] arr
is a simple reference passed by value. Use this if the native side also uses single indirection, eg. int32_t* arr
. Normally in C# if you pass an array by value (which is a reference type) the called method can replace the elements, which will be reflected from the caller side. However, P/Invoke marshaling works a bit differently:
By default, reference types (classes, arrays, strings, and interfaces) passed by value are marshaled as
In
parameters for performance reasons. You do not see changes to these types unless you applyInAttribute
andOutAttribute
(or justOutAttribute
) to the method parameter.
So the native side gets a correct pointer regardless of specifying the Out
attribute. Specifying [Out]
here is needed for the marshaler so it will not omit the copy-back session to the managed memory.
Similarly, in int length
will pass a reference to an integer and is not the same as [In] int length
, which passes the parameter simply by value. The [In]
can be omitted as this is the default marshaling behavior in this case.
Difference between ref and out parameters in .NET
They're pretty much the same - the only difference is that a variable you pass as an out
parameter doesn't need to be initialized but passing it as a ref
parameter it has to be set to something.
int x;
Foo(out x); // OK
int y;
Foo(ref y); // Error: y should be initialized before calling the method
Ref
parameters are for data that might be modified, out
parameters are for data that's an additional output for the function (eg int.TryParse
) that are already using the return value for something.
What's the difference between ref vs out parameter?
Both a ref parameter and an out parameter make an alias of a variable. That is, when you say:
M(int x) { ... }
...
int y = 123;
M(y);
then the value of y is passed, and x gets a copy of that value.
When you say
N(ref int x) { ... }
...
int y = 123;
N(ref y);
Then x and y are two names for the same variable. A change to x makes a change to y.
The only difference between ref and out from the caller's perspective is that the variable aliased by ref must be definitely assigned before the call. This is legal:
O(out int x) { ... }
...
int y; // no initialization!
O(out y);
But this is not:
N(ref int x) { ... }
...
int y; // no initialization!
N(ref y);
The only differences from the callee's perspective are:
- a
ref
parameter can be assumed to be initially assigned; anout
parameter cannot. an
out
parameter must be assigned before control leaves the method normally. That is, this is illegal:void O(out int x) { return; }
x
must be assigned before the return.
Behind the scenes, ref
and out
have the same implementation; the only difference is how the compiler tracks whether variables are assigned or not.
The guidelines for their use are:
- If you can avoid them, avoid them.
- If you cannot avoid them, use "out" when you are logically returning a value via modifying the variable and "ref" when you are reading the value of the variable and then possibly modifying the variable. An out must modify, and must not read (before the modification). A ref may modify and can read before modification.
What is diffrence between Out type Vs Ref type parameter in C#?
Both indicate to the caller that the method can modify the value of the parameter. out
parameters must be initialized inside the method whereas ref
parameters might be initialized outside. It's basically a contract. When you see a method that takes an out
parameter this means that that caller can invoke it without initializing the value and be sure that it will be initialized inside:
Foo foo;
SomeMethod(out foo);
// at this stage we know that foo will be initialized
whereas with ref:
Foo foo;
SomeMethod(ref foo); // compile time error
It's the caller's responsibility to initialize the variable before calling the method:
Foo foo = new Foo();
SomeMethod(ref foo); // ok
What is the difference between ref and out?
ref
parameters must be initialized before passing to function,the parameter may or may not be changed by the function.So you need to initialize it before you pass, like you do with non-ref arguments:
int i;
Foo(i); // error unassigned variable
Foo(ref i) // same error
For out
, your function guarantees that it will set the argument to a value.So it doesn't need to be initialized.
When should we use ref and out
Here is an example:
static void Main(string[] args)
{
int i = 1;
foo(i);
Console.Write(i); //i=1;
Reffoo(ref i);
Console.Write(i); //i=2;
}
static void Reffoo(ref int i)
{
i++;
}
static void foo(int i)
{
i++;
}
Why ref and out in C#?
The answer is given in this MSDN article. From that post:
The two parameter passing modes
addressed byout
andref
are subtly
different, however they are both very
common. The subtle difference between
these modes leads to some very common
programming errors. These include:
- not assigning a value to an
out
parameter in all control flow paths- not assigning a value to variable
which is used as aref
parameter
Because the C# language assigns
different definite assignment rules to
these different parameter passing
modes, these common coding errors are
caught by the compiler as being
incorrect C# code.The crux of the decision to include
bothref
andout
parameter passing
modes was that allowing the compiler
to detect these common coding errors
was worth the additional complexity of
having bothref
andout
parameter
passing modes in the language.
Related Topics
How to Perform a Left Outer Join Using Linq Extension Methods
How to Get C# Enum Description from Value
Why Would You Use String.Equals Over ==
Cast Generic≪Derived≫ to Generic≪Base≫
How to Update the Current Line in a C# Windows Console App
Entity Framework - Include Multiple Levels of Properties
Binding a Wpf Combobox to a Custom List
What Does Question Mark and Dot Operator . Mean in C# 6.0
How to Bind a Wpf Datagrid to a Variable Number of Columns
Reading Xml With Xmlreader in C#
Wix Installer Msi Not Installing the Winform App Created With Visual Studio 2017
Covariance and Contravariance Real World Example
How to Use Wpf Background Worker