I had a case where I thought tuples would work great. I needed to get the current performance statistics from a running operation (RunCount, AvgTime, MaxTime, MinTime, MeanTime, etc). The problem with this is that you need to lock() the call where the values are calculated in order to make sure it thread safe. So if I just had properties for RunCount, MaxTime etc then you can get values are are out of sync with each other.

Just like others have noted, the problem is that you don't know which value is which, and it is easy to get them mixed up, especially if some of them are of the same type (was AvgTime before MaxTime?). After trying it for a while I just gave up and return the statistics in a dedicated structure.

I though a solution would have been if you could have declared the tuple like this:

public class Operation
{
    public Tuple<int RunCount, TimeSpan MaxTime, TimeSpan MinTime, TimeSpan AvgTime> Statistics
    {
        get
        {
            lock (m_lock)
            {
                var tuple = new Tuple<int RunCount, TimeSpan MaxTime, TimeSpan MinTime, TimeSpan AvgTime>();
                tuple.RunCount = m_runs;
                ///etc...
                return tuple;
            }
        }
    }
}

// ...Then...

var stats = operation.Statistics;

runCountLabel.Text = stats.RunCount.ToString();
avgTimeLabel.Text = stats.AvgTime.ToString();
//...etc

It gets a bit verbose but then again it saves having to declare a dedicated structure ahead of time.