I prefer bool return with an out for TryXXX methods like TryParse, TryDeque etc. for a few reasons.
- The "parts" of the result are very separate things, and I like that they're kept separate.
- The return type is the same over all the variants of this. So that's consistent.
- The
out type is always one closely connected to the type or object called on, either by being the type itself (as in int.TryParse) or a type-parameter to the type (as in Dictionary<TKey, TValue>.TryGet and ConcurrentQueue<T>.TryDequeue). So that's consistent.
- It's become an easily recognisable pattern within .NET. So that's consistent.
The last point has a down-side in that people may turn to it when something else is more appropriate (assuming valid input and successful operation and throwing an exception if that in't the case, is often better).
I avoid out in other cases, it doesn't chain well, which in turn means it's not very handy in lambda expressions either.
I prefer an object that encapsulates the different values when it's likely to be of further use in itself. Otherwise it's just another class to learn about.
I prefer tuples when the there's a nice clear reason why something is returning two different values at the same time, but it doesn't fit with the above about a new object of use in itself.
I prefer only returning a single result in the first place, most of all.
With the car-fault example, I'd either return a single object that represented the fault that could be null if it wasn't faulty, a single object that represented the car's state of which "no faults found" could be a possible value, or best of all since cars can have more than one fault (and indeed seem to develop several expensive ones just before an NCT/MOT/your-country's-equivalent) an enumerable or queryable object that would let me iterate or query to find all the faults, which would be empty (as in Count == 0) if there were no faults.