Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning two values, Tuple vs 'out' vs 'struct'

Consider a function which returns two values. We can write:

// Using out: string MyFunction(string input, out int count)  // Using Tuple class: Tuple<string, int> MyFunction(string input)  // Using struct: MyStruct MyFunction(string input) 

Which one is best practice and why?

like image 418
Xaqron Avatar asked Jun 17 '11 06:06

Xaqron


People also ask

When would you use a tuple instead of a struct?

You use a struct for things that meaningfully belong together to form a whole. You use a tuple for things that are together coincidentally. You can use a tuple spontaneously in your code.

What is the advantage of tuple as returning function argument?

Tuples provide a third way of returning multiple function values, one that combines aspects of the structure-based and on-the-fly options already mentioned. With tuples, you define the values to be returned as part of the function declaration, a bit like the out-parameter variation.

What is an advantage of a class over a tuple?

One advantage of a named class is the will be easier to reuse (for example if you need the same type in multiple places) and document.

Is a tuple like a struct?

Structs are similar to tuples, discussed in “The Tuple Type” section, in that both hold multiple related values. Like tuples, the pieces of a struct can be different types. Unlike with tuples, in a struct you'll name each piece of data so it's clear what the values mean.


2 Answers

They each have their pros and cons.

Out parameters are fast and cheap but require that you pass in a variable, and rely upon mutation. It is almost impossible to correctly use an out parameter with LINQ.

Tuples create collection pressure1 and are un-self-documenting. "Item1" is not very descriptive.

Custom structs can be slow to copy if they are large, but are self-documenting and are efficient if they are small. However it is also a pain to define a whole bunch of custom structs for trivial uses.

I would be inclined to the custom struct solution all other things being equal. Even better though is to make a function that only returns one value. Why are you returning two values in the first place?

Note that tuples in C# 7, which shipped six years after this answer was written, are value types and hence less likely to create collection pressure.


1 Every time you allocate a small object off the heap, that puts "pressure" on the garbage collector. The more pressure, the more frequent collections. In some applications is it important to control the amount of collection pressure produced, so allocating a few million tuples unnecessarily can be a bad thing in those applications. Of course, like all questions of performance, don't blindly make changes until you understand the magnitude of the problem.

like image 195
Eric Lippert Avatar answered Sep 21 '22 08:09

Eric Lippert


Adding to the previous answers, C# 7 brings value type tuples, unlike System.Tuple that is a reference type and also offer improved semantics.

You can still leave them unnamed and use the .Item* syntax:

(string, string, int) getPerson() {     return ("John", "Doe", 42); }  var person = getPerson(); person.Item1; //John person.Item2; //Doe person.Item3;   //42 

But what is really powerful about this new feature is the ability to have named tuples. So we could rewrite the above like this:

(string FirstName, string LastName, int Age) getPerson() {     return ("John", "Doe", 42); }  var person = getPerson(); person.FirstName; //John person.LastName; //Doe person.Age;   //42 

Destructuring is also supported:

(string firstName, string lastName, int age) = getPerson()

like image 24
dimlucas Avatar answered Sep 20 '22 08:09

dimlucas