Как вернуть несколько значений из метода в C#?
Использование кортежей (Tuples) — современный способ
Начиная с C# 7.0, лучший способ вернуть несколько значений — использовать кортежи (tuples). Это тип, который может содержать несколько элементов разных типов. Кортежи делают код чистым, читаемым и избавляют от необходимости использовать out или создавать отдельные классы для каждой комбинации значений.
Базовый пример
public (int min, int max) FindMinMax(int[] numbers)
{
int min = numbers[0];
int max = numbers[0];
foreach (int num in numbers)
{
if (num < min) min = num;
if (num > max) max = num;
}
return (min, max);
}
// Использование:
var result = FindMinMax(new int[] { 3, 1, 7, 2, 9 });
Console.WriteLine($"Min: {result.min}, Max: {result.max}");
Именованные элементы кортежа
Вы можете дать элементам кортежа понятные имена прямо в сигнатуре метода:
public (int minimum, int maximum) FindMinMax(int[] numbers)
{
// ... логика ...
return (minimum: min, maximum: max);
}
// Доступ через имена:
var result = FindMinMax(data);
Console.WriteLine($"Min: {result.minimum}, Max: {result.maximum}");
Деконструкция кортежа (распаковка)
Можно сразу разложить результат на отдельные переменные:
(int min, int max) = FindMinMax(new int[] { 5, 2, 8, 1 });
Console.WriteLine($"Min: {min}, Max: {max}");
Альтернативные подходы (когда кортежи не подходят)
- Создание специального класса (DTO) — если значения логически связаны и используются в нескольких местах. Например, класс
MinMaxResultс полямиMinиMax. Это даёт документацию и возможность добавлять методы. - Использование
outпараметров — допустимо в старом коде или для методов Try-Pattern (например,int.TryParse), но в новых проектах лучше использовать кортежи. - Массив или список — если все значения одного типа и их количество нефиксировано. Например,
int[]для возврата набора чисел.
Рекомендации для реальных проектов
- Если метод возвращает 2-3 значения — используйте кортежи. Это минималистично и эффективно.
- Если возвращаемых значений больше 3 или они сложные (например, включают ссылочные типы) — создайте отдельный класс/структуру для ясности.
- Избегайте
outпараметров в новых API — они ухудшают читаемость и усложняют рефакторинг.
Пример с классом
public class MinMaxResult
{
public int Min { get; set; }
public int Max { get; set; }
}
public MinMaxResult FindMinMax(int[] numbers)
{
// ... логика ...
return new MinMaxResult { Min = min, Max = max };
}
Кортежи — это современный стандарт, принятый в C# сообществе. Они легковесны, поддерживают деконструкцию и не требуют дополнительных типов. Используйте их по умолчанию!
<<Использование record или структуры для возврата значений
Если вам нужно вернуть несколько значений, которые тесно связаны по смыслу и могут использоваться в разных частях программы, хорошим решением будет создать отдельный record или struct. Это даёт больше возможностей, чем кортежи: вы можете добавить методы, валидацию, документацию XML и переопределить ToString().
Пример с record (C# 9+)
public record MinMaxResult(int Min, int Max);
public MinMaxResult FindMinMax(int[] numbers)
{
int min = numbers[0];
int max = numbers[0];
// ... логика ...
return new MinMaxResult(min, max);
}
// Использование:
var result = FindMinMax(data);
Console.WriteLine(result); // Вывод: MinMaxResult { Min = 1, Max = 9 }
Когда это лучше кортежей?
- Когда возвращаемый набор значений имеет бизнес-смысл (например,
OrderSummary,UserCredentials). - Когда нужно переиспользовать тип в нескольких методах или классах.
- Когда планируете добавлять поведение (например, метод
IsValid()).
Record автоматически предоставляет сравнение по значению, неизменяемость (если не добавить set) и хороший вывод в консоль. Это более "тяжёлое", но и более выразительное решение, чем кортежи.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги