Best practice for using the "out" keyword in C #

I am trying to formalize the use of the "out" keyword in C # for the project I am working on, especially with respect to any public methods. It seems that I can’t find the best practices and would like to know what is good or bad.

Sometimes I see some method signatures that look like this:

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

At this moment, it’s just a feeling, it’s not very good with me. For some reason, I would rather see:

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

where the result is a type that contains a decimal number and some other number. I think it makes reading easier. This allows you to extend the result or add properties without breaking the code. It also means that the caller of this method does not need to declare a local cloud "someOtherNumber" before calling. From expectations of use, not all subscribers will be interested in "someOtherNumber".

In contrast, the only instances I can present right now in the framework of .Net where the "out" parameters make sense are methods like TryParse (). This actually forces the caller to write a simpler code in which the caller will be primarily interested in the out parameter.

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

I think that the "exit" should be used only if the return type is bool, and the expected conditions of use are where the "out" parameters will always interest the caller, by design.

Thoughts?

+16
c #
Jan 05 '09 at 14:16
source share
9 answers

There is one reason why one of the rules for static code analysis (= FxCop) points to you when you use the out parameters. I would say: use only out when it is really necessary in scripts like interop. In all other cases, just do not use out . But is it possible that only me?

+20
Jan 05 '09 at 14:22
source share

This is what . The .NET Framework Developer's Guide should talk about options:

Avoid using output or link options.

Working with members who define or reference parameters requires that the developer understand pointers, the subtle differences between value types and reference types, and initialize the differences between output and link parameters.

But if you use them :

Set all parameters after passing all the packages and references parameters (excluding the parameter of arrays), even if this leads to inconsistency in the ordering of parameters between overloads .

This convention makes the signature method easier to understand.

+14
Jan 05 '09 at 14:51
source share

Your approach is better than outside, because you can “catch” like this:

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

Unlike

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

TryParse methods implemented with "out" were a bug, IMO. That would be very convenient in chains.

+6
Jan 05 '09 at 14:29
source share

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

If, for example, you want to get the most common word in a text string and the 42nd word in a text, you can calculate them as in one method (you need to parse the text only once). But for your application, this data has nothing to do with each other: you need the most common word for statistical purposes, but you only need the 42nd word, because your client is a geeky fan of Douglas Adams.

Yes, this example is very far-fetched, but I have no better ...

+4
Jan 05 '09 at 14:31
source share

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

 int? i = Util.TryParseInt32("1"); if(i == null) return; DoSomething(i); 
+1
Jan 05 '09 at 14:23
source share

One of the benefits of out is that the compiler verifies that CalcSomething actually assigning someOtherNumber . It will not verify that the someOtherNumber field for Result is relevant.

+1
Jan 05 '09 at 14:29
source share

If you even saw and worked with the MS System.Web.Security namespace

 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 that breaks down many design paradigms. Awful

Just because the language has parameters does not mean that they should be used. e.g. goto

Using out. It seems that Dev was either lazy to create the type, or wanted to try the language function. Even a completely contrived example of MostCommonAnd42ndWord above I would use a List or a new type of contrivedresult with two properties.

The only good reasons that I saw in the explanations above were in the interaction scenarios when they were forced. Assuming this is a valid statement.

+1
Nov 28 '12 at 12:34
source share

You can create a general tuple class to return multiple values. This seems like a decent solution, but I can't help but feel that you are losing some readability by returning such a generic type ( Result is no better in this regard).

One important point, however, is that james curran also indicated that the compiler provides value assignment. This is a common pattern that I see in C # that you must explicitly specify certain things for more readable code. Another example of this is an override keyword that you don't have in Java.

0
Jan 05 '09 at 14:37
source share

If your result is more complex than one value, you should, if possible, create a result object. Reasons should I say this?

  • The whole result is encapsulated. That is, you have one package that informs the full result code CalcSomething. Instead of interpreting the value of the decimal value from the external code, you can specify the properties for your previous return value, your value someOtherNumber, etc.

  • You can include more complex success rates. The call you wrote may throw an exception if the end is before the start, but an exception is the only way to report errors. Using the result object, you can include a Boolean or enumerated Success value with the corresponding error message.

  • You can delay the execution of the result until the actual study of the "result" field. That is, the execution of any calculations should not be performed until you use the values.

0
Jan 05 '09 at 15:44
source share



All Articles