I despise out's and ref's as parameters on methods. IMHO, they make code less clean and provide opportunities for side-effects. But I concede that I may not understand their usefulness which might explain part of my loathing. Please, can someone explain a valid case for out's or ref's?
-
Are you asking the difference between the two, or what is the purpose of using either of them in general? And why is this tagged java? – Marlon Oct 15 '11 at 19:46
-
2How do you think they provide opportunities for side-effects? – svick Oct 15 '11 at 19:46
-
http://stackoverflow.com/questions/635915/when-to-use-ref-and-when-it-is-not-necessary-in-c-sharp – Petar Minchev Oct 15 '11 at 19:47
-
I guess you need to get serious with C++ to understand why it exists, irregardless of its C# applications – Theofanis Pantelides Oct 15 '11 at 20:13
-
The most common example of usage I run into in .NET is [`Dictionary.TryGetValue`](http://msdn.microsoft.com/en-us/library/bb347013.aspx) ... I'd argue this case is more cleanly handled by an Option/Maybe type and decomposition/pattern-matching, but the question is about C# and Dictionary is a "common/shared/base" .NET runtime class: that is, can't forget backwards compatibility, must work nicely in overall language/CLR design, and have a need to support VB.NET and other similar languages. – Oct 15 '11 at 20:19
4 Answers
Basically if you need to return more than one value, it's an alternative to using something like Tuple<,>
or a custom type to encapsulate the values. The canonical example is probably int.TryParse
and related methods. They want to convey two pieces of information back:
- The parsed value
- Whether or not parsing succeeded.
Now these could actually have been written using a return type of int?
etc in this case, but it's the same principle for other cases. (For example, Dictionary<,>.TryGetValue
, where the value stored in the dictionary may legitimately be null.)
I wouldn't say I despise out
and ref
parameters, but I do believe they should only be used occasionally, and only when there isn't a better alternative. Most of the uses of ref
I see on Stack Overflow are due to a misunderstanding of parameter passing.

- 1,421,763
- 867
- 9,128
- 9,194
-
@SaeedAmiri: Much the same, but you want the variable available as input as well. It's a bit like having an "in" parameter and another "out" parameter, except the caller can't separate the two :) – Jon Skeet Oct 15 '11 at 19:55
-
1Sorry a question, Why .net team decided use `out` in tryparse not `ref`? – Saeed Amiri Oct 15 '11 at 20:00
-
1@SaeedAmiri: Because the method doesn't need to know the existing value of the variable at all - why force the caller to pass in a value which isn't going to be used? The only benefit would be that it could be left with its current value on failure. – Jon Skeet Oct 15 '11 at 20:04
-
Ok, thanks, so ref is not good sample for this case, +1 for your help in comments – Saeed Amiri Oct 15 '11 at 20:08
-
Good explanation. I still hate outs and refs. An out param can't beat the expressiveness and clarity of a well named class. – Byron Sommardahl Oct 16 '11 at 00:36
out
provides a way to return more than one value. ref
is the same, except that you can also pass in a value.
Note that you can mutate an object even if is declared without ref
(assuming it is mutable in the first place of course).
The alternative I prefer to out
is to make a class to contain all the return values and return a single instance of that class.

- 811,555
- 193
- 1,581
- 1,452
-
1"out" parameters certainly do provide an opportunity for side effects -- they require that the method either run forever, terminate abnormally, *or mutate a variable*. That's a side effect. – Eric Lippert Oct 15 '11 at 21:21
The "new" (C# 4.0) lock
uses the ref
(technically the lock
statement is syntactic sugar for the new Monitor.Enter overload). It wouldn't be possible to do it without :-)
bool acquiredLock = false;
try
{
Monitor.Enter(lockObject, ref acquiredLock);
// Code that accesses resources that are protected by the lock.
}
finally
{
if (acquiredLock)
{
Monitor.Exit(lockObject);
}
}
so there is space for the ref
in highly critical places.
The reason why simply returning a bool value wouldn't be enough is that an exception could occur between the return true
of the Monitor.Enter
and the bool acquiredLock =
leaving your program with the question "was the lock tacken?" With the ref
parameter this problem is solved.

- 109,618
- 12
- 197
- 280
-
However, why not `var acquiredLock = Monitor.Enter(lockObject)`? I reject this is as being a *good need* for `ref`, although it is used. Arguably the standard `Dictionary.TryGetValue` is a better example as it has *two* values that must be returned (key found and value). – Oct 15 '11 at 20:14
-
@pst: Read the last paragraph again. You can't *return* whether the lock was taken because there might be an exception *between* when the return value was put "on the stack" and when the return value was copied into the variable. – Eric Lippert Oct 15 '11 at 21:23
-
@EricLippert, just curious: why does the `Monitor.Enter` method use `ref` and not `out`? While I know that they are the same at the IL level, this still requires that the programmer actually initializes the boolean, which seems pointless. Is there a reason or was this as simple oversight? – Lucero May 16 '12 at 17:53
-
@Lucero Because an `out` wouldn't guarantee initialization. There could be an exception after the `try` and before the `Monitor.Enter`. What would be the value of `acquiredLock`? – xanatos May 17 '12 at 06:56
-
@Lucero I'll add that if you try to write something like '`bool b; try { MyTest(out b); } finally { if (b) { } }` you'll get `Use of unassigned local variable 'b'` – xanatos May 17 '12 at 07:00
They're pretty much the same - the only difference is that a variable you pass as an out
parameter doesn't need to be initialised, and the method using the out
parameter has to set it to something.
int x;
Foo(out x);
int y;
Foo(ref y);
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.

- 17,397
- 27
- 100
- 203
-
1Is that true? What error do you get when a ref is not intialised? – Ash Burlaczenko Oct 15 '11 at 19:51
-
Also OP asked for their usage in .net (by knowing that good alternatives are available) not their difference, – Saeed Amiri Oct 15 '11 at 20:05
-
2@AshBurlaczenko: it certainly is true, and if you want to know what error you get, fire up the compiler and find out. – Eric Lippert Oct 15 '11 at 21:24