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

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.


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


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

For example, the TryParse methods take a out parameter to accept the parsed value, and return a bool to indicate whether or not the parse succeeded. The two values don't really belong together, so, semantically, it makes more sense, and the intent of the code is easier to read, to use the out parameter.

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

I'd personally avoid using a tuple for anything that will be visible to external code becuase of the awkward syntax for retrieving the members.