Я видел Кортеж, представленный в.Net 4, но я не могу вообразить, где он может использоваться. Мы можем всегда делать Пользовательский класс или Структуру.
В том-то и дело - удобнее , а не создавать собственный класс или структурировать все время. Это такое улучшение, как Action
или Func
... вы можете создавать эти типы самостоятельно, но удобно, что они существуют во фреймворке.
В журнале MSDN есть отличная статья , в которой рассказывается о боли в животе и дизайнерских соображениях, которые вошел в добавление кортежа в BCL. Выбор между типом значения и ссылочным типом особенно интересен.
Как ясно из статьи, движущей силой Tuple было то, что многие группы внутри Microsoft использовали его, и команда F # была впереди. Хотя это не упоминается, я считаю, что новое ключевое слово «dynamic» в C # (и VB.NET) тоже имеет какое-то отношение к этому, кортежи очень распространены в динамических языках.
В остальном это ничем не лучше, чем создание собственного поко, по крайней мере, вы можете дать участникам лучшее имя.
ОБНОВЛЕНИЕ: в связи с большой переработкой C # версии 7, теперь синтаксис стал намного популярнее. Предварительное объявление в этой записи блога .
Кортежи широко используются в функциональных языках которые могут делать с ними больше вещей, теперь F # является «официальным» языком .net, вы можете захотеть взаимодействовать с ним из C # и передавать их между кодом, написанным на двух языках.
Я использовал кортеж для решения Задачи 11 проекта Эйлер :
class Grid
{
public static int[,] Cells = { { 08, 02, 22, // whole grid omitted
public static IEnumerable<Tuple<int, int, int, int>> ToList()
{
// code converts grid to enumeration every possible set of 4 per rules
// code omitted
}
}
Теперь я могу решить всю проблему с помощью:
class Program
{
static void Main(string[] args)
{
int product = Grid.ToList().Max(t => t.Item1 * t.Item2 * t.Item3 * t.Item4);
Console.WriteLine("Maximum product is {0}", product);
}
}
Я мог бы использовать для этого пользовательский тип, но он выглядел бы точно так же, как Tuple .
Синтаксис кортежа C# смехотворно громоздкий, поэтому кортежи больно объявлять. И у него нет сопоставления шаблонов, поэтому они также болезненны в использовании.
Но иногда вам просто нужна специальная группировка объектов без создания класса для нее. Например, предположим, что я хотел агрегировать список, но мне нужны два значения вместо одного:
// sum and sum of squares at the same time
var x =
Enumerable.Range(1, 100)
.Aggregate((acc, x) => Tuple.Create(acc.Item1 + x, acc.Item2 + x * x));
Вместо того, чтобы объединять коллекцию значений в один результат, давайте расширим один результат в коллекцию значений. Проще всего записать эту функцию:
static IEnumerable<T> Unfold<T, State>(State seed, Func<State, Tuple<T, State>> f)
{
Tuple<T, State> res;
while ((res = f(seed)) != null)
{
yield return res.Item1;
seed = res.Item2;
}
}
f
преобразует некоторое состояние в кортеж. Возвращаем первое значение из кортежа и устанавливаем новое состояние на второе значение.Это позволяет нам сохранять состояние на протяжении всего вычисления.
Вы используете его как таковое:
// return 0, 2, 3, 6, 8
var evens =
Unfold(0, state => state < 10 ? Tuple.Create(state, state + 2) : null)
.ToList();
// returns 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
var fibs =
Unfold(Tuple.Create(0, 1), state => Tuple.Create(state.Item1, Tuple.Create(state.Item2, state.Item1 + state.Item2)))
.Take(10).ToList();
evens
довольно просто, но fibs
немного умнее. Его состояние
на самом деле является кортежем, который содержит fib(n-2) и fib(n-1) соответственно.
Вот небольшой пример - скажем, у вас есть метод, который должен искать дескриптор и адрес электронной почты пользователя по идентификатору пользователя. Вы всегда можете создать собственный класс, содержащий эти данные, или использовать параметр ref / out для этих данных, или вы можете просто вернуть Tuple и получить красивую подпись метода без необходимости создавать новый POCO.
public static void Main(string[] args)
{
int userId = 0;
Tuple<string, string> userData = GetUserData(userId);
}
public static Tuple<string, string> GetUserData(int userId)
{
return new Tuple<string, string>("Hello", "World");
}
Несколько примеров из моей головы:
Например, вы бы не ' Я не хочу включать System.Drawing в веб-приложение только для использования Point / PointF и Size / SizeF.