When should I use out parameters?
Asked Answered
I

10

62

I don't understand when an output parameter should be used, I personally wrap the result in a new type if I need to return more than one type, I find that a lot easier to work with than out.

I have seen method like this,

   public void Do(int arg1, int arg2, out int result)

are there any cases where that actually makes sense?

how about TryParse, why not return a ParseResult type? or in the newer framework return a null-able type?

Ilse answered 23/7, 2009 at 5:36 Comment(5)
You can write a wrapper around TryParse if you don't like it.Cesena
BTW, there is a Parse method as well, which has no out parameter and just returns a value. If the string can't be converted to the type, an exception is thrown.Quinine
Having a return type of void while using a single out parameter makes no sense, no. See some of the answers for good uses however.Lw
Even Microsoft themself recommends not using out parameters. msdn.microsoft.com/en-us/library/ms182131.aspx When you boil it down, out is a way of returning multiple values instead of just one. But it's cleaner and more modular for a function to return a struct or class that has everything you need to return in it.Linen
This question is similar to: Are "out" parameters a bad thing in .NET?. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem.Moores
P
33

Out is good when you have a TryNNN function and it's clear that the out-parameter will always be set even if the function does not succeed. This allows you rely on the fact that the local variable you declare will be set rather than having to place checks later in your code against null. (A comment below indicates that the parameter could be set to null, so you may want to verify the documentation for the function you're calling to be sure if this is the case or not.) It makes the code a little clearer and easier to read. Another case is when you need to return some data and a status on the condition of the method like:

public bool DoSomething(int arg1, out string result);

In this case the return can indicate if the function succeeded and the result is stored in the out parameter. Admittedly, this example is contrived because you can design a way where the function simply returns a string, but you get the idea.

A disadvantage is that you have to declare a local variable to use them:

string result;
if (DoSomething(5, out result))
    UpdateWithResult(result);

Instead of:

UpdateWithResult(DoSomething(5));

However, that may not even be a disadvantage, it depends on the design you're going for. In the case of DateTime, both means (Parse and TryParse) are provided.

Princessprinceton answered 23/7, 2009 at 5:43 Comment(5)
Actually, quite the opposite is true with regards to expecting the out parameter to remain unchanged after the call "fails". In most cases the out parameter must not be initialized before being passed into the function.Strawflower
" the out-parameter will not be changed if the function does not succeed." - The out parameter wil always be changed unless the function throws an exception. A method with an out parameter won't compile if it has an execution path that doesn't assign a value to the out parameter. Therefore the initialization 'string result = "";' in your second example is unnecessary.Winnah
What Samuel said. Setting an out parameter before exiting a method is required. If you want a value to be unchanged in some cases, use ref instead of out.Lw
The out parameter just saves the caller from having to initialize the variable. The method itself can still just initialize it to null or whatever default value, and return it that way.Unloosen
Now you don't need to declare a local variable anymore: if (DoSomething(5, out var result) { ... }.Acidfast
S
6

Well as with most things it depends. Let us look at the options

  • you could return whatever you want as the return value of the function
  • if you want to return multiple values or the function already has a return value, you can either use out params or create a new composite type that exposes all these values as properties

In the case of TryParse, using an out param is efficient - you dont have to create a new type which would be 16B of overhead (on 32b machines) or incur the perf cost of having them garbage collected post the call. TryParse could be called from within a loop for instance - so out params rule here.
For functions that would not be called within a loop (i.e. performance is not a major concern), returning a single composite object might be 'cleaner' (subjective to the beholder). Now with anonymous types and Dynamic typing , it might become even easier.

Note:

  1. out params have some rules that need to be followed i.e. the compiler will ensure that the function does initialize the value before it exits. So TryParse has to set the out param to some value even if parse operation failed
  2. The TryXXX pattern is a good example of when to use out params - Int32.TryParse was introduced coz people complained of the perf hit of catching exceptions to know if parse failed. Also the most likely thing you'd do in case parse succeeded, is to obtain the parsed value - using an out param means you do not have to make another method call to Parse
Socialistic answered 23/7, 2009 at 5:47 Comment(4)
I dont think there is an easy way to return anonymous type, is there?Corundum
Pre C#4.0, the trouble is in consuming these anon type return values. The method could return an anonymous object as an 'object', the caller however cannot do a returnValue.FirstEmbeddedValue even though it exists in the object. Need dynamic method resolution for this to work..Socialistic
@Socialistic -Is a composite type the same thing as a class?Tangier
@RadleyAnaya - composite => comprised of multiple things/values. Could be a C# class or struct.Socialistic
Q
6

I think out is useful for situations where you need to return both a boolean and a value, like TryParse, but it would be nice if the compiler would allow something like this:

bool isValid = int.TryParse("100", out int result = 0);
Quinine answered 23/7, 2009 at 5:53 Comment(2)
I like the declaration inline, I'd never thought of doing it that waySidonie
This is now available in C# 7Cantilever
K
6

Years late with an answer, I know. out (and ref as well) is also really useful if you do not wish your method do instantiate a new object to return. This is very relevant in high-performance systems where you want to achieve sub microsecond performance for your method. instantiating is relatively expensive seen from a memory access perspective.

Koa answered 8/10, 2015 at 21:11 Comment(0)
H
3

Definitely, out parameters are intended to be used when you have a method that needs to return more than one value, in the example you posted:

public void Do(int arg1, int arg2, out int result)

It doesn't makes much sense to use an out parameter, since you are only returning one value, and that method could be used better if you remove the out parameter and put a int return value:

public int Do(int arg1, int arg2)

There are some good things about out parameters:

  1. Output parameters are initially considered unassigned.
    • Every out parameter must be definitely assigned before the method returns, your code will not compile if you miss an assignment.

In conclusion, I basically try use out params in my private API to avoid creating separate types to wrap multiple return values, and on my public API, I only use them on methods that match with the TryParse pattern.

Harville answered 23/7, 2009 at 6:4 Comment(0)
B
1

Yes, it does make sense. Take this for example.

String strNum = "-1";
Int32 outNum;

if (Int32.TryParse(strNum, out outNum)) {
    // success
}
else {
    // fail
}

What could you return if the operation failed in a normal function with a return value? You most certainly could not return -1 to represent a fail, because then there would be no differentiation between the fail-return value and the actual value that was being parsed to begin with. This is why we return a Boolean value to see if it succeeded, and if it did then we have our "return" value safely assigned already.

Bickel answered 23/7, 2009 at 5:42 Comment(2)
you could return non existing type ParsedResult<T> : { bool Succes{get;} , T Result{get;}Deck
True, but this requires extra overhead of creating a return value type, when it's not required. TryParse already has all the functionality you could ever need for this scenario.Bickel
C
0

Creating a type just for returning values sounds little painful to me :-) First i will have to create a type for returning the value then in the calling method i have assign the value from the returned type to the actual variable that needs it.

Out parameters are simipler to use.

Corundum answered 23/7, 2009 at 5:40 Comment(0)
Q
0

It does annoy me that I can't pass in null to the out parameter for the TryParse functions.

Still, I prefer it in some cases to returning a new type with two pieces of data. Especially when they're unrelated for the most part or one piece is only needed for a single operation a moment after. When I do need to save the resulting value of a TryParse function I really like having an out parameter rather than some random ResultAndValue class that I have to deal with.

Qualifier answered 23/7, 2009 at 5:42 Comment(0)
B
0

If you always create a type, then you can end up with a lot of clutter in your application.

As said here, one typical use case is a TrySomething Method where you want to return a bool as an indicator for success and then the actual value. I also find that a little bit cleaner in an if-statement - all three options roughly have the same LOC anyway.

int myoutvalue;
if(int.TryParse("213",out myoutvalue){
    DoSomethingWith(myoutvalue);
}

vs.

ParseResult<int> myoutvalue = int.TryParse("213");
if ( myoutvalue.Success ) {
    DoSomethingWith(myoutvalue.Value);
}

vs.

int? myoutvalue = int.TryParse("213");
if(myoutvalue.HasValue){
    DoSomethingWith(myoutvalue.Value);
}

As for the "Why not return a Nullable Type": TryParse exists since Framework 1.x, whereas Nullable Types came with 2.0 (As they require Generics). So why unneccessarily break compatibility or start introducing inconsistencies between TryParse on some types? You can always write your own extension Method to duplicate functionality already existing (See Eric Lipperts Post on an unrelated subject that includes some reasoning behind doing/not doing stuff)

Another use case is if you have to return multiple unrelated values, even though if you do that that should trigger an alarm that your method is possibly doing too much. On the other hand, if your Method is something like an expensive database or web service call and you want to cache the result, it may make sense to do that. Sure, you could create a type, but again, that means one more type in your application.

Blackmarket answered 23/7, 2009 at 6:1 Comment(0)
U
-2

I use out parameters sometimes for readability, when reading the method name is more important than whatever the output of the method is—particularly for methods that execute commands in addition to returning results.

StatusInfo a, b, c;

Initialize(out a);
Validate(a, out b);
Process(b, out c);

vs.

StatusInfo a = Initialize();
StatusInfo b = Validate(a);
StatusInfo c = Process(b);

At least for me, I put a lot of emphasis on the first few characters of each line when I'm scanning. I can easily tell what's going on in the first example after acknowledging that some "StatusInfo" variables are declared. In the second example, the first thing I see is that a bunch of StatusInfo is retrieved. I have to scan a second time to see what kind of effects the methods may have.

Unloosen answered 23/7, 2009 at 5:54 Comment(4)
actually i think the first one looks alot worst!Ilse
I changed the names to something that closer resembles real-world code. I can dig up an actual example if this still looks bad.Unloosen
On the second one, the compiler will verify that you don't do them out of order. Not so with the first.Damning
@MitchBlevins -if that is the case then this is a horrible exmaple of when to use the out paramater... I think the second is much easier to read and understand. The first one is less typing thoughTangier

© 2022 - 2024 — McMap. All rights reserved.