18

As far as I can tell, the only use for out parameters is that a caller can obtain multiple return values from a single method invocation. But we can also obtain multiple result values using ref parameters instead!

So are there other situations where out parameters could prove useful and where we couldn't use ref parameters instead?

Thank you.

stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
flockofcode
  • 1,799
  • 2
  • 12
  • 21
  • NB: I've just posted [this answer](http://stackoverflow.com/questions/4102892/real-world-examples-where-c-out-parameters-are-useful/7220754#7220754) to a similar question where I describe a scenario where an `out` parameter is useful for something other than returning more than one value from a method. – stakx - no longer contributing Aug 28 '11 at 12:04

6 Answers6

29

Yes - the difference between ref and out is in terms of definite assignment:

  • An out parameter doesn't have to be definitely assigned by the caller before the method call. It does have to be definitely assigned in the method before it returns normally (i.e. without an exception). The variable is then definitely assigned in the caller after the call.

  • A ref parameter does have to be definitely assigned by the caller before the method call. It doesn't have to be assigned a different value in the method.

So suppose we wanted to change int.TryParse(string, out int) to use ref instead. Usually the calling code looks like this:

int value;
if (int.TryParse(text, out value))
{
    // Use value
}
else
{
    // Do something else
}

Now if we used ref, we'd have to give value a value before the call, e.g.:

int value = 0;
if (int.TryParse(text, ref value))
{
    // Use value
}
else
{
    // Do something else
}

Obviously it's not a huge difference - but it gives the wrong impression. We're assigning a value that we have no intention of ever using, and that's not a good thing for readability. An out parameter indicates that a value will come out of the method (assuming there's no exception) and that you don't need to have a value to start with.

Once of the suggestions I've made for C# 5 (I've no idea if it'll be taken up or not) is that a method with an out parameter should be able to regarded as a method returning a tuple of values. Combined with better support for tuples, that would mean we could do something like this:

var (ok, value) = int.TryParse(text);

In this case ok and value would be implicitly typed to bool and int respectively. That way it's clear what's going into the method (text) and what's coming out (two pieces of information: ok and value).

That would simply not be available if int.TryParse used a ref parameter instead - as the compiler can't know whether it's going to actually care about the initial value of the ref parameter.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • +1 - I like the idea of a tuple result value implied by out parameters. – Thomas Jun 27 '10 at 19:09
  • 1
    @Thomas: It's not original - I pinched it from F# :) – Jon Skeet Jun 27 '10 at 19:32
  • 1
    _(Somewhat off-topic:)_ Agree with Jon on his request for tuple "unpacking" (whatdoyoucallit). I still don't understand why such a big fuss was made about support for tuples in .NET / C# 4.0 -- and that they apparently even had to adapt the CLR for it -- while at the same time that very handy feature was left out. Sort of makes the `Tuple` type look very trivial, if not even nearly useless. – stakx - no longer contributing Jun 27 '10 at 19:56
  • @stakx: I hadn't heard anything about tuple support requiring a CLR change. Do you have a link for further information? – Jon Skeet Jun 27 '10 at 20:54
  • @stakx: Tuples were mainly added to the BCL in order to unify the different, incompatible *existing* Tuple types from all the .NET languages that have Tuples natively, like Python or F#. Similar to big number arithmetic. I don't think there was ever any intention of surfacing them in any of the languages that didn't already support them. Not that that wouldn't be great, of course. Ideally with even more general pattern matching or at least general destructuring bind, not just for Tuples. – Jörg W Mittag Jun 27 '10 at 22:12
  • @Jeff I really hope they implement your suggestion. It's one of my favorite features of Python. Saves a lot of throw-away-class creation and unnecessary packing/unpacking. – Evan Plaice Jun 27 '10 at 22:12
  • @Jon: I heard about about tuples and the CLR in a PDC 2008 session recording ("Microsoft .NET Framework: CLR Futures", online @ http://channel9.msdn.com/pdc2008/PC49/). My comment above is due to one inaccurate slide in that talk: While the slide presented around time index 00:13:15 suggests that the *CLR* was changed to allow tuples, a later slide (around time index 00:16:06) states that tuples were included in the *BCL* for interoperability (basically what Jörg commented above). That makes far better sense, too. (Still a bit strange to hear about the BCL in a talk about the CLR...) – stakx - no longer contributing Jun 28 '10 at 20:04
8

You can look at parameters in this way:

  • normal parameters are in parameters:
    A value can go into the function through such a parameter; therefore it must be initialized.

  • ref parameters are in-out parameters:
    A value can go into and out of a function through such a parameter. Because of the former, it must also be initialized.

  • out parameters are out parameters:
    A value is only supposed to come back from a function through such a parameter; therefore, it doesn't need to be initialized.

I came up with this way of looking at ref/out parameters by studying Microsoft's COM technology. IDL (interface description language) is used to describe COM component interfaces, and with IDL, parameters are augmented with in, out, and inout declarators. I suspect .NET and C# have partly inherited these declarators from COM, albeit with slightly different names (ref instead of inout).

With COM, out parameters are frequently used to retrieve an interface method's actual return value, since the "real" return value is often already used for returning a HRESULT success/error code.

With .NET, I think out parameters have far less importance, even in cases where you want to return several values from a method (you could return complex objects or Tuples in these situations).

stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
4

One important difference is this:

A variable passed as an out argument need not be initialized. However, the out parameter must be assigned a value before the method returns.

(A ref parameter does not require this)

Source: http://msdn.microsoft.com/en-us/library/t3c3bfhx(VS.71).aspx

code4life
  • 15,655
  • 7
  • 50
  • 82
2

An out parameter is useful when you want multiple result values from a method. Technically, you could use a ref parameter to achieve the same goal but an out parameter does a significantly better job at conveying intent. When you use ref, It is not clear why you are doing so instead of using out or instead of using the function result. Presumably, you intend on changing the value passed, but why you are changing it isn't clear simply from the function signature.

Thomas
  • 63,911
  • 12
  • 95
  • 141
2

I think a fine example is int.TryParse()

http://msdn.microsoft.com/en-us/library/f02979c7.aspx

The primary reason that out is better than ref is that you don't need to assign a dummy value to the return var before calling (even implicitly).

So out tells you, and the compiler: "This var will be assigned within the method. And the var's initial value, if any, will not even be looked at."

Detmar
  • 713
  • 4
  • 6
0

Major difference between the two is that if we are using ref then we have to initialize this before call and it is optional that we assign a value to our ref variable in our method.

However for out methods we do not have to explicitly initialize them but in our method we have to assign some value to it, otherwise they will generate compile time error.

Zeeshan Umar
  • 502
  • 2
  • 6
  • 12