.Net 3.5 не поддерживает кортежи. Жаль, но не уверен, будет ли будущая версия .net поддерживать кортежи или нет?





#region tuples
public class Tuple<T>
{
public Tuple(T first)
{
First = first;
}
public T First { get; set; }
}
public class Tuple<T, T2> : Tuple<T>
{
public Tuple(T first, T2 second)
: base(first)
{
Second = second;
}
public T2 Second { get; set; }
}
public class Tuple<T, T2, T3> : Tuple<T, T2>
{
public Tuple(T first, T2 second, T3 third)
: base(first, second)
{
Third = third;
}
public T3 Third { get; set; }
}
public class Tuple<T, T2, T3, T4> : Tuple<T, T2, T3>
{
public Tuple(T first, T2 second, T3 third, T4 fourth)
: base(first, second, third)
{
Fourth = fourth;
}
public T4 Fourth { get; set; }
}
#endregion
А чтобы декларации красивее:
public static class Tuple
{
//Allows Tuple.New(1, "2") instead of new Tuple<int, string>(1, "2")
public static Tuple<T1, T2> New<T1, T2>(T1 t1, T2 t2)
{
return new Tuple<T1, T2>(t1, t2);
}
//etc...
}
Хотя вопрос заключается в том, что MS предоставляет его в .NET 4, на данный момент это хороший способ справиться с этим. +1
Такой подход наследования хорош, если вам не нужно сравнивать два кортежа на равенство. Я хотел реализовать IEquatable <Tuple <T1, T2 >> и т.д. в своей реализации, поэтому я не мог использовать наследование, потому что я не хотел, чтобы Tuple <T1, T2> был равен Tuple <T1, Т2, Т3, Т4>.
@Joel, Equals может проверить динамический тип обоих аргументов.
Как бы вы использовали это в коде? t = новый кортеж (1, 2); т. во-первых и т. во-вторых?
См. Также еще один ответ на аналогичный вопрос: stackoverflow.com/questions/955982/…
@drozzy, нет, вам нужно будет сделать t = new Tuple <int, int> (1, 2);
@dimarzionist, извините за редактирование вашего сообщения, я пробовал оставить комментарий, но он не читается, не стесняйтесь удалять или изменять.
Я вижу, вы используете наследование - вы действительно хотите иметь возможность передавать Tuple<T1,T2,T3> как Tuple<T1,T2>? Скорее всего, нет.
Если я правильно помню свои уроки информатики, кортежи - это просто данные.
Если вам нужны сгруппированные данные - создайте классы, содержащие свойства. Если вам нужно что-то вроде KeyValuePair, то вот оно.
Точно так же, как операторы if - это просто gotos с блоком операторов. Кортежи хороши, если вы привыкли к ним, а классы кажутся ненужными и громоздкими в определенных случаях ...
Если вам не нужно возвращать 5 элементов из функции, то есть. Конечно, вы можете создать собственный общий класс, но синтаксис в C# 7 намного чище и проще.
Я был бы удивлен - C# - это строго типизированный язык, тогда как кортежи подходят для более динамически типизированных языков. C# со временем становится все более динамичным, но это синтаксический сахар, а не реальный сдвиг в базовых типах данных.
Если вам нужно два значения в одном экземпляре, KeyValuePair <> является достойной заменой, хотя и неуклюжей. Вы также можете создать структуру или класс, которые будут делать то же самое и могут быть расширены.
«C# стал более динамичным» - нет, он стал более неявным / предполагаемым; это все еще полностью статический язык. Однако лучшая динамическая поддержка (для использования классов DLR), скорее всего, станет усовершенствованием языка в будущем.
Как вы объясните наличие кортежей в F#, Haskell или любом другом строго и статически типизированном языке, который их полностью поддерживает ...?
На мой взгляд, функция анонимных типов - это не кортеж, а очень похожая конструкция. Результатом некоторых запросов LINQ являются коллекции анонимных типов, которые ведут себя как кортежи.
Вот инструкция, которая на лету создает типизированный кортеж :-):
var p1 = new {a = "A", b = 3};
см .: http://www.developer.com/net/csharp/article.php/3589916
C# довольно легко поддерживает простые кортежи с помощью универсальных шаблонов (согласно предыдущему ответу), а с «бормотанием» (одно из многих возможных усовершенствований языка C#) для улучшения вывода типов они могут быть очень и очень мощными.
Как бы то ни было, F# поддерживает кортежи изначально, и, поиграв с ним, я не уверен, что (анонимные) кортежи добавляют много ... то, что вы получаете в краткости, вы быстро теряете очень в ясности кода.
Для кода внутри одного метода существуют анонимные типы; для кода, выходящего за рамки метода, я думаю, что буду придерживаться простых именованных типов. Конечно, если в будущем C# будет проще сделать их неизменяемыми (при этом с ними легко работать), я буду счастлив.
Одно из преимуществ - для таких вещей, как TryParse, где вы можете написать 'valid value = double.TryParse ("1.02")' и назначить несколько возвращаемых значений без каких-либо неуклюжих параметров out. Но в целом я согласен с тем, что чисто позиционные структуры данных - не лучшее дело.
Согласовано - множественные возвращаемые значения - лучший вариант использования кортежей, кроме этого, для кортежей в коде очень мало смысла. Это должно быть условием, а не ограничением, хотя там, где разрешены кортежи. Я думаю, было бы лучше, если бы языки .NET предоставляли способ «разбивать» возвращаемые объекты на несколько значений, а не вводить тип данных кортеж. Что-то вроде { j = ErrorCode, h = ResultObj } = SomeFunction() (где j и h - местные) было бы гораздо полезнее, чем кортежи.
Реализация классов Tuple или повторное использование классов F# в C# - это только половина дела - они дают вам возможность относительно легко создавать кортежи, но не синтаксический сахар, который делает их такими удобными для использования в таких языках, как F#.
Например, в F# вы можете использовать сопоставление с образцом для извлечения обеих частей кортежа внутри let, например
let (a, b) = someTupleFunc
К сожалению, сделать то же самое с использованием классов F# из C# было бы гораздо менее элегантно:
Tuple<int,int> x = someTupleFunc();
int a = x.get_Item1();
int b = x.get_Item2();
Кортежи представляют собой мощный метод для возврата нескольких значений из вызова функции без необходимости засорять ваш код одноразовыми классами или прибегать к некрасивым параметрам ref или out. Однако, на мой взгляд, без некоторого синтаксического сахара, делающего их создание и доступ более элегантным, они имеют ограниченное применение.
Как насчет анонимных типов?
Это позволяет вам заменить Tuple <int, int> на var, но вы все равно получите три строки кода, а не одну
Возможно, это то, что мы увидим в C# 4.0. Синтаксический сахар, такой как int a, b = someTupleFunc (); должно быть прекрасно выполнимо на уровне компилятора.
Чтобы сделать их полезными в хэш-таблице или словаре, вы, вероятно, захотите предоставить перегрузки для GetHashCode и Equals.
Вот мой набор кортежей, они автоматически сгенерированы скриптом Python, поэтому я, возможно, немного переборщил:
Ссылка на репозиторий Subversion
Вам понадобится имя пользователя / пароль, они оба гость
Они основаны на наследовании, но Tuple<Int32,String> не будет сравниваться с Tuple<Int32,String,Boolean>, даже если они имеют одинаковые значения для двух первых членов.
Они также реализуют GetHashCode, ToString и т. д., А также множество небольших вспомогательных методов.
Пример использования:
Tuple<Int32, String> t1 = new Tuple<Int32, String>(10, "a");
Tuple<Int32, String, Boolean> t2 = new Tuple<Int32, String, Boolean>(10, "a", true);
if (t1.Equals(t2))
Console.Out.WriteLine(t1 + " == " + t2);
else
Console.Out.WriteLine(t1 + " != " + t2);
Выведет:
10, a != 10, a, True
Но это еще не все. Если это основано на наследовании, я полагаю, вы могли бы написать Tuple<Int32, String> t1 = new Tuple<Int32, String, Boolean>(10, "a", true); и т. д. Я не уверен, есть ли какой-либо сценарий, который это желательно.
В Общие библиотеки Lokad (конечно, с открытым исходным кодом) есть реализация правильный (не быстрая) Кортеж C#, которая включает следующие необходимые функции:
Я только что прочитал эту статью из журнала MSDN: Построение кортежа
Вот выдержки:
The upcoming 4.0 release of Microsoft .NET Framework introduces a new type called System.Tuple. System.Tuple is a fixed-size collection of heterogeneously typed data.
Like an array, a tuple has a fixed size that can't be changed once it has been created. Unlike an array, each element in a tuple may be a different type, and a tuple is able to guarantee strong typing for each element.
There is already one example of a tuple floating around the Microsoft .NET Framework, in the System.Collections.Generic namespace: KeyValuePair. While KeyValuePair can be thought of as the same as Tuple, since they are both types that hold two things, KeyValuePair feels different from Tuple because it evokes a relationship between the two values it stores (and with good reason, as it supports the Dictionary class).
Furthermore, tuples can be arbitrarily sized, whereas KeyValuePair holds only two things: a key and a value.
Хотя некоторые языки, такие как F#, имеют специальный синтаксис для кортежей, вы можете использовать новый общий тип кортежей из любого языка. Возвращаясь к первому примеру, мы видим, что хотя и полезны, кортежи могут быть излишне подробными на языках без синтаксиса для кортежа:
class Program {
static void Main(string[] args) {
Tuple<string, int> t = new Tuple<string, int>("Hello", 4);
PrintStringAndInt(t.Item1, t.Item2);
}
static void PrintStringAndInt(string s, int i) {
Console.WriteLine("{0} {1}", s, i);
}
}
Используя ключевое слово var из C# 3.0, мы можем удалить сигнатуру типа в переменной кортежа, что позволяет сделать код более читаемым.
var t = new Tuple<string, int>("Hello", 4);
Мы также добавили некоторые фабричные методы в статический класс Tuple, что упрощает создание кортежей на языке, поддерживающем вывод типов, например C#.
var t = Tuple.Create("Hello", 4);
В моем .NET Библиотека Sasa с открытым исходным кодом уже много лет используются кортежи (наряду с множеством других функций, таких как полный анализ MIME). Я использую его в производственном коде уже несколько лет.
C# 7 изначально поддерживает кортежи:
var unnamedTuple = ("Peter", 29);
var namedTuple = (Name: "Peter", Age: 29);
(string Name, double Age) typedTuple = ("Peter", 29);
Это работает из коробки, начиная с .NET 4.7, поскольку более старые версии .NET не содержат необходимых структур ValueTuple. Однако вы можете предоставить их, например, с помощью пакета NuGet, такого как ValueTupleBridge.
Теперь у MS есть официальный пакет nuget для требуемых классов кортежей.
.NET 4 поддерживает кортежи msdn.microsoft.com/en-us/library/system.tuple.aspx