24

I'm trying to formalise the usage of the "out" keyword in c# for a project I'm on, particularly with respect to any public methods. I can't seem to find any best practices out there and would like to know what is good or bad.

Sometimes I'm seeing some methods signatures that look like this:

public decimal CalcSomething(Date start, Date end, out int someOtherNumber){}

At this point, it's just a feeling, this doesn't sit well with me. For some reason, I'd prefer to see:

public Result CalcSomething(Date start, Date end){}

where the result is a type that contains a decimal and the someOtherNumber. I think this makes it easier to read. It allows Result to be extended or have properties added without breaking code. It also means that the caller of this method doesn't have to declare a locally scoped "someOtherNumber" before calling. From usage expectations, not all callers are going to be interested in "someOtherNumber".

As a contrast, the only instances that I can think of right now within the .Net framework where "out" parameters make sense are in methods like TryParse(). These actually make the caller write simpler code, whereby the caller is primarily going to be interested in the out parameter.

int i;
if(int.TryParse("1", i)){
  DoSomething(i);
}

I'm thinking that "out" should only be used if the return type is bool and the expected usages are where the "out" parameters will always be of interest to the caller, by design.

Thoughts?

  • 3
    "Out" of "int"erest (shoot me now), what comes out in someOtherNumber in the example? – Rob Jan 05 '09 at 14:20
  • 1
    I would never use out for just a boolean output value; this feels odd. I'd rather return the boolean and use out for larger values (just like in your TryParse example). – Pierre Arnaud Jan 05 '09 at 14:24
  • Pierre - I suspect that the OP meant that you can use an out parameter if you have something like the TryParse example, where the bool is returned, rather than being the out parameter. – Ant Jan 05 '09 at 15:39

10 Answers10

22

There is a reason that one of the static code analysis (=FxCop) rules points at you when you use out parameters. I'd say: only use out when really needed in interop type scenarios. In all other cases, simply do not use out. But perhaps that's just me?

peSHIr
  • 6,279
  • 1
  • 34
  • 46
  • 1
    Just found this: http://msdn.microsoft.com/en-us/library/ms182131.aspx, CA1021: AvoidOutParameters. FxCop rule... good enough for me. Thank you. –  Jan 05 '09 at 14:44
  • Notice this rule explicitly mentions only protected and public methods as being a problem. What about using `out` in internal methods? – heltonbiker Feb 25 '15 at 18:36
  • My answer is the same for private/internal methods: only use out parameters if absolutely needed in interop type scenarios.. – peSHIr Feb 26 '15 at 11:23
19

This is what the .NET Framework Developer's Guide has to say about out parameters:

Avoid using out or reference parameters.

Working with members that define out or reference parameters requires that the developer understand pointers, subtle differences between value types and reference types, and initialization differences between out and reference parameters.

But if you do use them:

Do place all out parameters after all of the pass-by-value and ref parameters (excluding parameter arrays), even if this results in an inconsistency in parameter ordering between overloads.

This convention makes the method signature easier to understand.

Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541
  • 26
    So the Developer's Guide is basically saying that you shouldn't use out parameters because most developers are too stupid to understand a very elementary aspect of their chosen language!! – Stephen Martin Jan 05 '09 at 14:57
  • 1
    Stephen, that is so true. I say use them where you need them. – Lamar Jan 06 '09 at 06:13
  • 1
    As a Java developer, whenever I've seen functions modify one of their inputs, it's usually in a poorly designed class. I'm guessing that "out" is an example a keyword that was created for a few specific cases. – U Avalos Jan 07 '14 at 23:17
6

Your approach is better than out, because you can "chain" calls that way:

DoSomethingElse(DoThing(a,b).Result);

as opposed to

DoThing(a, out b);
DoSomethingElse(b);

The TryParse methods implemented with "out" was a mistake, IMO. Those would have been very convenient in chains.

Giovanni Galbo
  • 12,963
  • 13
  • 59
  • 78
  • 2
    Well, you need a way to tell if the parsing succeeded. – lacop Jan 05 '09 at 16:04
  • 2
    For chaining, use `int.Parse()`, or pass the unparsed string. I don't see how you could get `TryParse()` functionality without using `out` parameters. – gilly3 Mar 29 '13 at 20:58
4

There are only very few cases where I would use out. One of them is if your method returns two variables that from an OO point of view do not belong into an object together.

If for example, you want to get the most common word in a text string, and the 42nd word in the text, you could compute both in the same method (having to parse the text only once). But for your application, these informations have no relation to each other: You need the most common word for statistical purposes, but you only need the 42nd word because your customer is a geeky Douglas Adams fan.

Yes, that example is very contrived, but I haven't got a better one...

Treb
  • 19,903
  • 7
  • 54
  • 87
  • Even then, I would use an class/struct (or tuple instance from 4.0 onwards). Something like the contrived `MostCommonAnd42thWordResult`, but still. Or of course design the entire logic differently, to work around the "contrividness" and "do not belong into an object together-feeling" of this example. ;-) – peSHIr Jan 21 '10 at 07:28
3

I just had to add that starting from C# 7, the use of the out keyword makes for very readable code in certain instances, when combined with inline variable declaration. While in general you should rather return a (named) tuple, control flow becomes very concise when a method has a boolean outcome, like:

if (int.TryParse(mightBeCount, out var count)
{
    // Successfully parsed count
}

I should also mention, that defining a specific class for those cases where a tuple makes sense, more often than not, is more appropriate. It depends on how many return values there are and what you use them for. I'd say, when more than 3, stick them in a class anyway.

aitchgee
  • 31
  • 5
1

If you have even seen and worked with MS namespace System.Web.Security

MembershipProvider 
   public abstract MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status);

You will need a bucket. This is an example of a class breaking many design paradigms. Awful!

Just because the language has out parameters doesn't mean they should be used. eg goto

The use of out Looks more like the Dev was either Lazy to create a type or wanted to try a language feature. Even the completely contrived MostCommonAnd42ndWord example above I would use List or a new type contrivedresult with 2 properties.

The only good reasons i've seen in the explanations above was in interop scenarios when forced to. Assuming that is valid statement.

phil soady
  • 11,043
  • 5
  • 50
  • 95
1

Stay away from out. It's there as a low-level convenience. But at a high level, it's an anti-technique.

int? i = Util.TryParseInt32("1");
if(i == null)
    return;
DoSomething(i);
yfeldblum
  • 65,165
  • 12
  • 129
  • 169
1

One advantage of out is that the compiler will verify that CalcSomething does in fact assign a value to someOtherNumber. It will not verify that the someOtherNumber field of Result has a value.

James Curran
  • 101,701
  • 37
  • 181
  • 258
  • 1
    My approach here would be to enforce the someOtherNumber field to be initialized via the Result constructor. –  Jan 05 '09 at 14:41
  • 2
    FYI - only the C# compiler will do this. You can flagrantly break this contract in other .NET languages. – plinth Jan 05 '09 at 15:56
0

You could create a generic tuple class for the purpose of returning multiple values. This seems to be a decent solution but I can't help but feel that you lose a bit of readability by returning such a generic type (Result is no better in that regard).

One important point, though, that james curran also pointed out, is that the compiler enforces an assignment of the value. This is a general pattern I see in C#, that you must state certain things explicitly, for more readable code. Another example of this is the override keyword which you don't have in Java.

Morten Christiansen
  • 19,002
  • 22
  • 69
  • 94
0

If your result is more complex than a single value, you should, if possible, create a result object. The reasons I have to say this?

  1. The entire result is encapsulated. That is, you have a single package that informs the code of the complete result of CalcSomething. Instead of having external code interpret what the decimal return value means, you can name the properties for your previous return value, Your someOtherNumber value, etc.

  2. You can include more complex success indicators. The function call you wrote might throw an exception if end comes before start, but exception throwing is the only way to report errors. Using a result object, you can include a boolean or enumerated "Success" value, with appropriate error reporting.

  3. You can delay the execution of the result until you actually examine the "result" field. That is, the execution of any computing needn't be done until you use the values.

Tom Moseley
  • 591
  • 7
  • 15