📦 Return Multiple Values Elegantly
Creating class for one method? Using out parameters? Ugly. Tuples return multiple values cleanly.
The Old Ways (Painful)
// ❌ Out parameters (ugly)
public void GetStats(out int count, out decimal total, out decimal avg)
{
count = 100;
total = 5000m;
avg = 50m;
}
// Ugly usage
GetStats(out int count, out decimal total, out decimal avg);
// ❌ Creating class for single use
public class Stats
{
public int Count { get; set; }
public decimal Total { get; set; }
public decimal Average { get; set; }
}
public Stats GetStats() { /* ... */ }
The Tuple Way (Elegant)
// ✅ Named tuple
public (int Count, decimal Total, decimal Average) GetStats()
{
var count = 100;
var total = 5000m;
var avg = 50m;
return (count, total, avg);
}
// Clean usage
var stats = GetStats();
Console.WriteLine($"Count: {stats.Count}");
Console.WriteLine($"Total: {stats.Total:C}");
// Or deconstruct
var (count, total, avg) = GetStats();
Console.WriteLine($"Average: {avg:C}");
🎯 Real-World Examples
// Parse with validation
public (bool Success, int Value) TryParseInt(string input)
{
if (int.TryParse(input, out int result))
return (true, result);
return (false, 0);
}
var (success, value) = TryParseInt("123");
if (success)
Console.WriteLine($"Parsed: {value}");
// Min/Max in one pass
public (int Min, int Max) GetMinMax(int[] numbers)
{
return (numbers.Min(), numbers.Max());
}
var (min, max) = GetMinMax(new[] { 1, 5, 3, 9, 2 });
// Coordinates
public (double Lat, double Lng) GetLocation()
{
return (37.7749, -122.4194);
}
var location = GetLocation();
Console.WriteLine($"Lat: {location.Lat}, Lng: {location.Lng}");
💡 Pro Tips
- Always name tuple elements:
(int Count, decimal Total)not(int, decimal) - Deconstruct selectively:
var (count, _) = GetStats();to ignore values - Pattern matching: Works with switch expressions
- When not to use: If returned from many places, use proper class
“Deleted 15 single-use DTOs. Replaced with named tuples. Code is cleaner, less ceremony, same type safety. Tuples are underrated.”
