When should you use options?

I don’t understand when the output parameter should be used, I personally transfer the result to a new type, if I need to return more than one type, I find it much easier to work with it than with.

I saw such a method,

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

Are there any cases where this really makes sense?

what about TryParse , why not return the ParseResult type? or in the new structure return the zero method?

+42
c # out
Jul 23 '09 at 5:36
source share
10 answers

The output is good if you have a TryNNN function, and it is clear that the out parameter will always be set, even if the function fails. This allows you to rely on the fact that the local variable you are declaring will be set instead of putting checks later in your code with a null value. (The comment below indicates that the parameter can be set to null , so you can check the documentation for the function you are calling to make sure it is or not.) This makes the code a little understandable and easier to read. Another case is when you need to return some data and status to the state of the method, for example:

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

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

The downside is that you have to declare a local variable in order to use them:

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

Instead:

 UpdateWithResult(DoSomething(5)); 

However, this may not even be a drawback, it depends on the design that you are going to use. In the case of DateTime, both tools (Parse and TryParse) are provided.

+24
Jul 23 '09 at 5:43
source share
— -

Well, as in most cases, it depends. Let's look at the options

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

In the case of TryParse, efficient use of the out parameter - you do not need to create a new type that would be 16B overhead (on 32-bit machines), or entail the full cost of collecting garbage after the call. For example, TryParse can be called from a loop, so the params rule is here. For functions that will not be called in a loop (i.e., Performance is not a serious problem), the return of one composite object can be "cleaner" (the subject of the observer). Now with anonymous types and dynamic typing, this can be made even simpler.

Note:

  • out params have some rules that must be followed, that is, the compiler ensures that the function initializes the value before it exits. Thus, TryParse must set the out parameter to some value, even if the parsing operation has failed.
  • The TryXXX template is a good example of when to use parameters - Int32.TryParse was introduced because people complained about the performance of exception hits to find out if the parsing failed. In addition, the most likely thing you could do if the parsing succeeded is to get the parsed value - using the out parameter means you don't have to make another method call in Parse
+5
Jul 23 '09 at 5:47
source share

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

 bool isValid = int.TryParse("100", out int result = 0); 
+3
Jul 23 '09 at 5:53
source share

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

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

It makes no sense to use the out parameter, since you return only one value, and this method can be used better if you remove the out parameter and put the return value int:

 public int Do(int arg1, int arg2) 

There are some good things about options:

  • Output parameters are initially considered unassigned.
    • Each parameter must be defined definitely before the method returns, your code will not compile if you miss the assignment.

In conclusion, I mainly try to use parameters in my private API to avoid creating separate types for transferring multiple return values, and also in my public API, I use them only for methods that match the TryParse pattern.

+2
Jul 23 '09 at 6:04
source share

A few years later with the answer, I know. out (and ref) is also very useful if you do not want your method to instantiate a new object to return. This is very relevant in high-performance systems where you want to achieve micromicros performance for your method. instantiation is relatively expensive in terms of memory access.

+1
Oct 08 '15 at 21:11
source share

Creating a type only for return values ​​sounds a little painful for me :-) First I need to create a type to return a value, and then in the calling method I will assign the value from the returned type to the actual variable that it needs.

Output parameters can be used as a simulator.

0
Jul 23 '09 at 5:40
source share

Yes, that makes 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? Of course, you would not be able to return -1 to represent a failure, because then there would be no difference between the error return value and the actual value that started from the beginning. That is why we return a boolean value to see if he managed to do it, and if that were done, we would already get our "return" value.

0
Jul 23 '09 at 5:42
source share

It annoys me that I cannot pass a null value to the out parameter for TryParse functions.

However, I prefer in some cases to return a new type with two pieces of data. Especially when they are not connected for the most part, or one part is needed only for one operation in an instant. When I need to save the final value of the TryParse function, I really like to have the out parameter, and not some random ResultAndValue class that I have to deal with.

0
Jul 23 '09 at 5:42
source share

Sometimes I use parameters for readability when reading a method name is more important than what the method outputs, especially 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); 

against.

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

At least for me, I pay much attention to the first few characters of each line when scanning. I can easily tell what happens in the first example after confirming 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 repeat a second time to see what effects methods can have.

0
Jul 23 '09 at 5:54
source share

If you always create a type, then there may be a lot of mess in your application.

As said here, one typical use case is the TrySomething method, in which you want to return bool as an indicator of success, and then the actual value. I also find it a little cleaner in if-statement - all three options are about the same for LOC.

 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); } 

Regarding "Why not return a Nullable Type": TryParse exists with Framework 1.x, while Nullable Types exists with 2.0 (since they require Generics). So why carelessly break compatibility or start introducing inconsistencies between TryParse on some types? You can always write your own extension method to duplicate existing functions (see Eric Lipperts Post for an unrelated topic that includes some arguments for doing / not doing things)

Another use case is if you need to return multiple unrelated values, even if you do this, which should cause an alarm that your method may be doing too much. On the other hand, if your method is a bit of an expensive database or web service call and you want to cache the result, it might make sense to do this. Of course, you can create a type, but again, this means that there will be another type in your application.

0
Jul 23 '09 at 6:01
source share



All Articles