411

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?

Sina Lotfi
  • 3,044
  • 1
  • 23
  • 30
Dale
  • 12,884
  • 8
  • 53
  • 83
  • 19
    A variable passed in using `out` cannot be read from before it's assigned to. `ref` does not have this restriction. So there's that. – Corey Ogburn Dec 26 '13 at 18:08
  • 20
    In short, `ref` is for in/out, while `out` is an out-only parameter. – Tim S. Dec 26 '13 at 18:10
  • 3
    What exactly don't you get? – tnw Dec 26 '13 at 18:11
  • 4
    Also `out` variables HAVE to be assigned to in the function. – Corey Ogburn Dec 26 '13 at 18:12
  • Thanks Corey. But i already not that. My point is that what is the benefit of this. Actually I need an example that shows a scenario where we can use ref parameter to achieve a functionality that can not be achieved by using out parameter and vice verse. – Rajbir Singh Dec 26 '13 at 18:14
  • Guys Corey, Tim S, tnw, Dan Hunex don't try to underestimate a person. – Rajbir Singh Dec 26 '13 at 18:23
  • @tnw i am not taking it as personal. Actually you guys didn't try to understand what i was asking in my question and i didn't like it. zneak is a guy who actually put efforts to answer my question. And i am really happy i got answer of my question. Anything else doesn't matter. That's it. – Rajbir Singh Dec 26 '13 at 19:57
  • @tnw i don't think so. First i have googled this question when i didn't get any proper answer only then i put this question here and i thought this is the right place to get proper answer. But you said it is off-topic which again doesn't make sense. – Rajbir Singh Dec 26 '13 at 20:04
  • Read the off-topic close votes: "Questions **asking for code** must demonstrate a minimal understanding of the problem being solved. Include **attempted solutions**, why they didn't work, and the expected results." If you don't understand when exactly to use one over the other, you haven't read the documentation thoroughly enough. – tnw Dec 26 '13 at 20:07
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/43966/discussion-between-rajbir-singh-and-tnw) – Rajbir Singh Dec 27 '13 at 05:44
  • possible duplicate of [What's the difference between the 'ref' and 'out' keywords?](http://stackoverflow.com/questions/388464/whats-the-difference-between-the-ref-and-out-keywords) – Dexters Jan 22 '14 at 19:12
  • Here is the detail explanation for out vs ref https://youtu.be/3iRPMrNY7OU – Parveen Oct 30 '22 at 11:37

17 Answers17

415

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.

peterchen
  • 40,917
  • 20
  • 104
  • 186
  • 1
    That isn't really the case. You should use out if you just want a extra return variables. ref allow for bi-directional variables. Really out is ref with an extra attribute taged on it. – Matthew Whited Oct 04 '09 at 17:59
  • 5
    "That isn't really the case." - can you please explain better what you mean? – peterchen Oct 05 '09 at 08:49
  • What about passing 'default' values into a TryXxx style method? Using 'out' would clobber the default, so you would need to use 'ref'. But then that is not necessarily idiomatic is it? – Chris Oldwood Sep 28 '10 at 11:05
  • 3
    You don't want to use `ref` for default values. – C.Evenhuis Nov 18 '11 at 13:22
  • 167
    For posterity: One other difference no one else seems to have mentioned, as stated [here](http://msdn.microsoft.com/en-us/library/t3c3bfhx%28v=VS.80%29.aspx); for an `out` parameter, **the calling method is _required_ to assign a value before the method returns.** - you don't _have_ to do anything with a ref parameter. – brichins Dec 20 '11 at 22:59
  • 3
    @brichins Please refer to the 'comments (Community Additions)' section in the [link](http://msdn.microsoft.com/en-us/library/t3c3bfhx%28v=VS.80%29.aspx) mentioned by you. It is an error which is corrected in VS 2008 documentation. – Bharat Ram V Aug 12 '13 at 08:07
  • You are not correct about the big difference concerning performance gain on out parameters relative to ref ones. Out parameter values do actually get marshaled into the called method just like ref parameters. – Zverev Evgeniy Oct 03 '13 at 21:27
  • @zverev.eugene: this, however, is an implementation detail that could be changed without violating the contract. In the default (in-process) case it might even be cheaper. I'm not familiar enough with .NET remote call implementaiton to say any more - maybe you can provide a reference. – peterchen Oct 04 '13 at 07:41
  • 14
    @brichins the *called* method is required to assign a value, not the calling method. zverev.eugene this is what was corrected in the VS 2008 documentation. – Segfault Mar 26 '14 at 21:53
  • @Segfault Correct - I know the proper terminology is "called", but by the time I noticed the mistake it was far too late to edit my comment. The main point I was making though is the requirement to assign. – brichins Mar 27 '14 at 22:50
  • Here is the detail explanation for out vs ref https://youtu.be/3iRPMrNY7OU – Parveen Oct 30 '22 at 11:37
78

Use out to denote that the parameter is not being used, only set. This helps the caller understand that you're always initializing the parameter.

Also, ref and out are not just for value types. They also let you reset the object that a reference type is referencing from within a method.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 3
    +1 I didn't know that it can be used for reference types too, nice clear answer, thanks – Dale Oct 04 '09 at 23:40
  • @brichins: No you can't. `out` parameters are treated as unassigned on entry to the function. You won't be able to inspect their value until you have first definitely assigned some value -- there is no way at all to use the value the parameter had when the function was called. – Ben Voigt Dec 26 '13 at 18:27
  • True, you cannot access the value prior to an internal assignment. I was referring to the fact that the parameter itself *can* be used later in the method - it is not locked. Whether this should actually be done or not is a different discussion (on design); I just wanted to point out it was possible. Thanks for the clarification. – brichins Dec 27 '13 at 23:18
  • 2
    @ดาว: It can be used with reference types because when you pass in a reference type parameter, what you are passing is the value of the reference not the object itself. So it is still pass-by-value. – Tarik Dec 22 '14 at 17:01
41

You're correct in that, semantically, ref provides both "in" and "out" functionality, whereas out only provides "out" functionality. There are some things to consider:

  1. out requires that the method accepting the parameter MUST, at some point before returning, assign a value to the variable. You find this pattern in some of the key/value data storage classes like Dictionary<K,V>, where you have functions like TryGetValue. This function takes an out parameter that holds what the value will be if retrieved. It wouldn't make sense for the caller to pass a value into this function, so out is used to guarantee that some value will be in the variable after the call, even if it isn't "real" data (in the case of TryGetValue where the key isn't present).
  2. out and ref parameters are marshaled differently when dealing with interop code

Also, as an aside, it's important to note that while reference types and value types differ in the nature of their value, every variable in your application points to a location of memory that holds a value, even for reference types. It just happens that, with reference types, the value contained in that location of memory is another memory location. When you pass values to a function (or do any other variable assignment), the value of that variable is copied into the other variable. For value types, that means that the entire content of the type is copied. For reference types, that means that the memory location is copied. Either way, it does create a copy of the data contained in the variable. The only real relevance that this holds deals with assignment semantics; when assigning a variable or passing by value (the default), when a new assignment is made to the original (or new) variable, it does not affect the other variable. In the case of reference types, yes, changes made to the instance are available on both sides, but that's because the actual variable is just a pointer to another memory location; the content of the variable--the memory location--didn't actually change.

Passing with the ref keyword says that both the original variable and the function parameter will actually point to the same memory location. This, again, affects only assignment semantics. If a new value is assigned to one of the variables, then because the other points to the same memory location the new value will be reflected on the other side.

Adam Robinson
  • 182,639
  • 35
  • 285
  • 343
  • 1
    Note that the requirement that the called method assign a value to an out parameter is enforced by the c# compiler, and not by the underlying IL. So, a library written in VB.NET may not conform to that convention. – jmoreno Mar 01 '14 at 22:36
  • Sounds like the ref is actually the equivalent of the dereferencing symbol in C++ (*). Passby reference in C# must be equivalent to what C/C++ refers to as double pointers (pointer to a pointer) so ref must dereference the 1st pointer, allowing the called method access to the memory location of the actual object in context. – ComeIn Nov 26 '14 at 01:37
  • I actually would suggest a correct `TryGetValue` would use `ref` and not `out` explicitly in the case of not finding the key. – NetMage Nov 01 '17 at 21:25
28

It depends on the compile context (See Example below).

out and ref both denote variable passing by reference, yet ref 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:

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

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

static class outRefTest{
    public static int myfunc(int x){x=0; return x; }
    public static void myfuncOut(out int x){x=0;}
    public static void myfuncRef(ref int x){x=0;}
    public static void myfuncRefEmpty(ref int x){}
    // Define other methods and classes here
}

in CIL, the instructions of myfuncOut and myfuncRef are identical as expected.

outRefTest.myfunc:
IL_0000:  nop         
IL_0001:  ldc.i4.0    
IL_0002:  starg.s     00 
IL_0004:  ldarg.0     
IL_0005:  stloc.0     
IL_0006:  br.s        IL_0008
IL_0008:  ldloc.0     
IL_0009:  ret         

outRefTest.myfuncOut:
IL_0000:  nop         
IL_0001:  ldarg.0     
IL_0002:  ldc.i4.0    
IL_0003:  stind.i4    
IL_0004:  ret         

outRefTest.myfuncRef:
IL_0000:  nop         
IL_0001:  ldarg.0     
IL_0002:  ldc.i4.0    
IL_0003:  stind.i4    
IL_0004:  ret         

outRefTest.myfuncRefEmpty:
IL_0000:  nop         
IL_0001:  ret         

nop: no operation, ldloc: load local, stloc: stack local, ldarg: load argument, bs.s: branch to target....

(See: List of CIL instructions )

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
Lorenz Lo Sauer
  • 23,698
  • 16
  • 85
  • 87
25

Below are some notes which i pulled from this codeproject article on C# Out Vs Ref

  1. It should be used only when we are expecting multiple outputs from a function or a method. A thought on structures can be also a good option for the same.
  2. REF and OUT are keywords which dictate how data is passed from caller to callee and vice versa.
  3. In REF data passes two way. From caller to callee and vice-versa.
  4. In Out data passes only one way from callee to caller. In this case if Caller tried to send data to the callee it will be overlooked / rejected.

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

C# Out Vs Ref

Shivprasad Koirala
  • 27,644
  • 7
  • 84
  • 73
  • 1
    `one-way` , `two-way` terms might be misused here. They actually are both two-way, however their conceptual behaviors differs on parameters' references and values – ibubi Aug 13 '17 at 11:30
19

You need to use ref if you plan to read and write to the parameter. You need to use out 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), and out 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.

int x;
Foo(ref x); // error: x is uninitialized

void Bar(out int x) {}  // error: x was not written to

For instance, int.TryParse returns a bool and accepts an out int parameter:

int value;
if (int.TryParse(numericString, out value))
{
    /* numericString was parsed into value, now do stuff */
}
else
{
    /* numericString couldn't be parsed */
}

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 the int could have been before.

For ref, you can look at Interlocked.Increment:

int x = 4;
Interlocked.Increment(ref x);

Interlocked.Increment atomically increments the value of x. Since you need to read x to increment it, this is a situation where ref is more appropriate. You totally care about what x was before it was passed to Increment.

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:

if (int.TryParse(numericString, out int value))
{
    // 'value' exists and was declared in the `if` statement
}
else
{
    // conversion didn't work, 'value' doesn't exist here
}
zneak
  • 134,922
  • 42
  • 253
  • 328
  • Thanks zneak for your response. But can you explain me why i could not use out for read and write a parameter ? – Rajbir Singh Dec 26 '13 at 18:49
  • 1
    @RajbirSingh, because `out` parameters haven't necessarily been initialized, so the compiler won't let you read from an `out` parameter until you've written something to it. – zneak Dec 26 '13 at 18:54
  • zneak, I agreed with you. But in below example a out parameter can be used as read and write: string name = "myName"; private void OutMethod(out string nameOut) { if(nameOut=="myName") { nameOut = "Rajbir Singh in out method"; } } – Rajbir Singh Dec 26 '13 at 19:00
  • 1
    @RajbirSingh, your example doesn't compile. You cannot read `nameOut` in your `if` statement because it wasn't assigned anything before. – zneak Dec 26 '13 at 19:07
  • Thanks @zneak. You are absolutely right. It doesn't compile. Thanks a lot for my help and now it makes sense to me :) – Rajbir Singh Dec 26 '13 at 19:16
  • This is a great answer to a [different question](http://stackoverflow.com/questions/1516876/when-to-use-ref-vs-out). I hope that the moderators will merge your answer into that question before we delete this one. – John Saunders Dec 26 '13 at 19:31
  • FYI: merged here from http://stackoverflow.com/questions/20789153/ref-vs-out-parameters-in-c-sharp – Shog9 Jan 18 '14 at 02:03
11

How to use in or out or ref in C#?

  • All keywords in C# have the same functionality but with some boundaries.
  • in arguments cannot be modified by the called method.
  • ref arguments may be modified.
  • ref must be initialized before being used by caller it can be read and updated in the method.
  • out arguments must be modified by the caller.
  • out arguments must be initialized in the method
  • Variables passed as in arguments must be initialized before being passed in a method call. However, the called method may not assign a value or modify the argument.

You can't use the in, ref, and out keywords for the following kinds of methods:

  • Async methods, which you define by using the async modifier.
  • Iterator methods, which include a yield return or yield break statement.
Sina Lotfi
  • 3,044
  • 1
  • 23
  • 30
  • "out arguments must be modified by the caller." - I don't think that's true at all. See https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-parameter-modifier. It only specifies that the called method is required to assign a value to the out variable – emilaz Nov 14 '22 at 10:05
9

Still feel the need for a good summary, this is what I came up with.

Summary,

When we are inside the function, this is how we specify the variable data access control,

in = R

out = must W before R

ref = R+W


Explanation,

in

Function may only READ that variable.

out

Variable must not be initialised first because,
function MUST WRITE to it before READ.

ref

Function may READ/WRITE to that variable.


Why is it named as such?

Focusing on where data gets modified,

in

Data must only be set before entering (in) function.

out

Data must only be set before leaving (out) function.

ref

Data must be set before entering (in) function.
Data may be set before leaving (out) function.

tinker
  • 483
  • 4
  • 16
  • maybe (in/out/ref) should be renamed to (r/wr/rw). or maybe not, in/out is a nicer metaphor. – tinker Oct 07 '19 at 09:12
7

out is more constraint version of ref.

In a method body, you need to assign to all out parameters before leaving the method. Also an values assigned to an out parameter is ignored, whereas ref requires them to be assigned.

So out allows you to do:

int a, b, c = foo(out a, out b);

where ref would require a and b to be assigned.

leppie
  • 115,091
  • 17
  • 196
  • 297
  • If anything, `out` is the less constrained version. `ref` has "Precondition: variable is definitely assigned, Postcondition: variable is definitely assigned", while `out` has only `Postcondition: variable is definitely assigned". (And as expected, more is required of a function implementation with fewer preconditions) – Ben Voigt Dec 26 '13 at 18:30
  • @BenVoigt: Guess that depends what direction you looking at :) I think I meant constraint in terms of coding flexibility (?). – leppie Dec 26 '13 at 19:23
7

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.

Shneor
  • 304
  • 3
  • 4
6

You can use the out contextual keyword in two contexts (each is a link to detailed information), as a parameter modifier or in generic type parameter declarations in interfaces and delegates. This topic discusses the parameter modifier, but you can see this other topic for information on the generic type parameter declarations.

The out keyword causes arguments to be passed by reference. This is like the ref keyword, except that ref requires that the variable be initialized before it is passed. To use an out parameter, both the method definition and the calling method must explicitly use the out keyword. For example: C#

class OutExample
{
    static void Method(out int i)
    {
        i = 44;
    }
    static void Main()
    {
        int value;
        Method(out value);
        // value is now 44
    }
}

Although variables passed as out arguments do not have to be initialized before being passed, the called method is required to assign a value before the method returns.

Although the ref and out keywords cause different run-time behavior, they are not considered part of the method signature at compile time. Therefore, methods cannot be overloaded if the only difference is that one method takes a ref argument and the other takes an out argument. The following code, for example, will not compile: C#

class CS0663_Example
{
    // Compiler error CS0663: "Cannot define overloaded 
    // methods that differ only on ref and out".
    public void SampleMethod(out int i) { }
    public void SampleMethod(ref int i) { }
}

Overloading can be done, however, if one method takes a ref or out argument and the other uses neither, like this: C#

class OutOverloadExample
{
    public void SampleMethod(int i) { }
    public void SampleMethod(out int i) { i = 5; }
}

Properties are not variables and therefore cannot be passed as out parameters.

For information about passing arrays, see Passing Arrays Using ref and out (C# Programming Guide).

You can't use the ref and out keywords for the following kinds of methods:

Async methods, which you define by using the async modifier.

Iterator methods, which include a yield return or yield break statement.

Example

Declaring an out method is useful when you want a method to return multiple values. The following example uses out to return three variables with a single method call. Note that the third argument is assigned to null. This enables methods to return values optionally. C#

class OutReturnExample
{
    static void Method(out int i, out string s1, out string s2)
    {
        i = 44;
        s1 = "I've been returned";
        s2 = null;
    }
    static void Main()
    {
        int value;
        string str1, str2;
        Method(out value, out str1, out str2);
        // value is now 44
        // str1 is now "I've been returned"
        // str2 is (still) null;
    }
}
Ali Jamal
  • 844
  • 11
  • 19
5

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:

private void Nullify(StringBuilder sb, string message)
{
    sb.Append(message);
    sb = null;
}

// -- snip --

StringBuilder sb = new StringBuilder();
string message = "Hi Guy";
Nullify(sb, message);
System.Console.WriteLine(sb.ToString());

// Output
// Hi Guy

As apposed to this:

private void Nullify(ref StringBuilder sb, string message)
{
    sb.Append(message);
    sb = null;
}

// -- snip --

StringBuilder sb = new StringBuilder();
string message = "Hi Guy";
Nullify(ref sb, message);
System.Console.WriteLine(sb.ToString());

// Output
// NullReferenceException
ParmesanCodice
  • 5,017
  • 1
  • 23
  • 20
5

Basically both ref and out for passing object/value between methods

The out keyword causes arguments to be passed by reference. This is like the ref keyword, except that ref requires that the variable be initialized before it is passed.

out : Argument is not initialized and it must be initialized in the method

ref : Argument is already initialized and it can be read and updated in the method.

What is the use of “ref” for reference-types ?

You can change the given reference to a different instance.

Did you know?

  1. Although the ref and out keywords cause different run-time behavior, they are not considered part of the method signature at compile time. Therefore, methods cannot be overloaded if the only difference is that one method takes a ref argument and the other takes an out argument.

  2. You can't use the ref and out keywords for the following kinds of methods:

    • Async methods, which you define by using the async modifier.
    • Iterator methods, which include a yield return or yield break statement.
  3. Properties are not variables and therefore cannot be passed as out parameters.

CharithJ
  • 46,289
  • 20
  • 116
  • 131
4

An argument passed as ref must be initialized before passing to the method whereas out parameter needs not to be initialized before passing to a method.

vml19
  • 3,816
  • 11
  • 45
  • 63
4

why do you ever want to use out?

To let others know that the variable will be initialized when it returns from the called method!

As mentioned above: "for an out parameter, the calling method is required to assign a value before the method returns."

example:

Car car;
SetUpCar(out car);
car.drive();  // You know car is initialized.
RayLoveless
  • 19,880
  • 21
  • 76
  • 94
4

Extra notes regarding C# 7:
In C# 7 there's no need to predeclare variables using out. So a code like this:

public void PrintCoordinates(Point p)
{
  int x, y; // have to "predeclare"
  p.GetCoordinates(out x, out y);
  WriteLine($"({x}, {y})");
}

Can be written like this:

public void PrintCoordinates(Point p)
{
  p.GetCoordinates(out int x, out int y);
  WriteLine($"({x}, {y})");
}

Source: What's new in C# 7.

Saber
  • 5,150
  • 4
  • 31
  • 43
0

It should be noted that in is a valid keyword as of C# ver 7.2:

The in parameter modifier is available in C# 7.2 and later. Previous versions generate compiler error CS8107 ("Feature 'readonly references' is not available in C# 7.0. Please use language version 7.2 or greater.") To configure the compiler language version, see Select the C# language version.

...

The in keyword causes arguments to be passed by reference. It makes the formal parameter an alias for the argument, which must be a variable. In other words, any operation on the parameter is made on the argument. It is like the ref or out keywords, except that in arguments cannot be modified by the called method. Whereas ref arguments may be modified, out arguments must be modified by the called method, and those modifications are observable in the calling context.

Community
  • 1
  • 1
Mr_Engineer
  • 256
  • 1
  • 6