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

Consider a function that 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?

+58
c # struct tuples value-type out
Jun 17 '11 at 6:01
source share
6 answers

Each of them has its pros and cons.

Parameter options are fast and cheap, but require you to pass a variable and rely on a mutation. It is almost impossible to correctly use the out parameter with LINQ.

Tuples produce pressure on collection and are not self-documenting. "Item1" is not very descriptive.

Custom structures can be slowly copied if they are large, but self-documenting and effective if they are small. However, it is also painful to define a whole bunch of custom structures for trivial use.

I would be inclined to have a custom structural solution ceteris paribus. Better yet, however, is to make a function that returns only one value. Why are you returning two values ​​first?

UPDATE: note that tuples in C # 7, which were posted six years after writing this article, are value types and are therefore less likely to create pressure in the collection.

+72
Jun 17 2018-11-11T00:
source share

I think the answer depends on the semantics of what the function performs and on the relationship between the two values.

For example, the TryParse methods take an out parameter to accept the parsed value and return a bool to indicate whether parsing was successful. These two values ​​do not really belong together, so semantically it makes sense, and the purpose of the code is easier to read in order to use the out parameter.

If, however, your function returns the X / Y coordinates of some object on the screen, then the two values ​​semantically belong to each other, and it would be better to use a struct .

I would personally avoid using tuple for everything that will be visible to the external code due to the inconvenient syntax for retrieving members.

+13
Jun 17 2018-11-11T00:
source share

Adding to the previous answers, C # 7 adds value type tuples, unlike System.Tuple , which is a reference type, and also offers 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 in this new feature is the ability to have named tuples. Therefore, we could rewrite the above as follows:

 (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()

+5
Jun 06 '17 at 11:44 on
source share

I’ll go with the approach to using the Out parameter, because in the second approach you will need to create an object of the Tuple class and then add a value to it, which, in my opinion, is an expensive operation compared to returning a value from the out parameter. Although, if you want to return multiple values ​​to the Tuple Class (which cannot be achieved by simply returning one out parameter), I will send a second approach.

+1
Jun 17 2018-11-11T00:
source share

You did not specify another parameter that has a custom class type instead of a class. If the data has semantics associated with it that functions can influence, or the instance size is large enough (> 16 bytes as a rule), a custom class may be preferable. Using "out" is not recommended in the public API because of its association with pointers and requires an understanding of how reference types work.

https://msdn.microsoft.com/en-us/library/ms182131.aspx

Tuple is good for internal use, but its use is inconvenient in the public API. So my vote depends on the structure and class for the public API.

+1
Aug 31 '16 at 17:44
source share

There is no "best practice." This is what you are comfortable with and what works best in your situation. If you agree with this, there is no problem with any solutions you posted.

0
Jun 17 2018-11-11T00:
source share



All Articles