Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Value tuples exist, so why use the "out" parameter modifier? [closed]

Tags:

c#

out

valuetuple

Microsoft's documentation for the out parameter modifier points out the following:

Declaring a method with out arguments is a classic workaround to return multiple values. Consider value tuples for similar scenarios.

This strikes me as a remarkably good point. What use case remains for out, now that we have value tuples?

like image 752
J. Mini Avatar asked Sep 03 '25 06:09

J. Mini


2 Answers

One major use case I can think of off the top of my head are Try... methods that return a value and a boolean so that you can check whether the action succeded or not:

// With out parameters:
if(int.TryParse(someString, out int result)){
   // do something with the int
}

// With tuples:
var (success, value) = int.TryParseWithTuples(someString);
if(success){
   // do something with the int
}

With the out parameter, the notation is cleaner and results in less lines (and doesn't require you to create a local variable for the success boolean). It also allows you to do this:

if(int.TryParse(someString, out int r1)){
   // do something with the int
} else if(int.TryParse(fallbackString, out int r2)){
   // do something with the fallback int
} else {
   throw new InvalidOperationException();
}

With tuples, this would look like this:

var (success, value) = int.TryParseWithTuples(someString);
if(success){
   // do something with the int
} else {
   (success, value) = int.TryParseWithTuples(fallbackString);
   if(success){
       // do something with the fallback int
   } else {
       throw new InvalidOperationException();
   }
}
like image 114
ascpixi Avatar answered Sep 04 '25 20:09

ascpixi


In addition to the ease of use of the TryX pattern, as pointed out by ascpixi, another case that makes a value-tuple unsuitable as a return type is when one of the two values is a reference. For example take a look at the CollectionsMarshal.GetValueRefOrAddDefault API:

public static ref TValue? GetValueRefOrAddDefault<TKey,TValue> (
    Dictionary<TKey,TValue> dictionary,
    TKey key,
    out bool exists);

It is used like this:

ref int refValue = ref CollectionsMarshal.GetValueRefOrAddDefault(
    dictionary, key, out bool exists);

if (!exists) refValue = 1; else refValue++;

The ValueTuple<T1, T2> is not a ref struct, so it could not be used for this API. Theoretically this API could return a custom tuple-like ref struct, but in that case it would lack the language support that exists only for real value-tuples, like the shorthand notation with parentheses etc.

like image 29
Theodor Zoulias Avatar answered Sep 04 '25 21:09

Theodor Zoulias