2008-09-30 1 views

ответ

73

Я только что прочитал эту статью из журнала MSDN Magazine: Building Tuple

Вот выдержки:

Предстоящий выпуск Microsoft +4,0 .NET Framework вводит новый тип под названием System .Tuple. System.Tuple представляет собой набор с фиксированным размером разнородных данных.

Как массив, кортеж имеет фиксированное размер, который не может быть изменен, как только она была создана. В отличие от массива, каждый элемент в кортеже может быть другим типом , а кортеж может гарантировать строгую типизацию для каждого элемента .

Существует уже один пример кортежа плавающим вокруг Microsoft .NET Framework , в System.Collections.Generic имен: KeyValuePair. Хотя KeyValuePair можно рассматривать как же как кортежи, так как они оба типа, которые держат две вещей, KeyValuePair чувствует отличается от кортежей, потому что он вызывает зависимость между этими двумя значениями, которые он хранит (и по уважительной причине, поскольку он поддерживает класс словаря ).

Кроме того, кортежи могут быть произвольно , тогда как KeyValuePair имеет только две вещи: ключ и значение.


Хотя некоторые языки, такие как 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); 
    } 
} 

Использования УАК ключевого слова из C# 3.0, мы можем удалить тип подпись на переменном кортеж , что позволяет получить более читаемый код.

var t = new Tuple<string, int>("Hello", 4); 

Мы также добавили некоторые фабричные методы для статического класса кортежа, что делает его легче построить кортежи на языке, который поддерживает определение типа, как C#.

var t = Tuple.Create("Hello", 4); 
69
#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... 
} 
+1

Хотя вопрос находится на МС обеспечения это в .NET 4, это хороший способ управлять им на данный момент. +1 – 2008-09-30 07:03:50

+6

Этот подход наследования хорош, если вам не нужно сравнивать два набора для равенства. Я хотел реализовать IEquatable > и т. Д. В моей реализации, поэтому я не мог использовать наследование, потому что я не хотел, чтобы Tuple был равен Tuple . – 2008-12-03 18:35:43

+3

@Joel. У вас может быть Equals проверять динамический тип обоих аргументов. – RossFabricant 2009-04-05 17:49:46

2

Если я помню свои компьютерные классы науки правильно кортежи только данные.

Если вы хотите сгруппировать данные - создайте классы, содержащие свойства. Если вам нужно что-то вроде KeyValuePair, то вот оно.

0

Я был бы удивлен - C# - строго типизированный язык, в то время как кортежи подходят для более динамически типизированных языков. С течением времени C# дрейфует с большей динамичностью, но это синтаксический сахар, а не реальный сдвиг в базовых типах данных.

Если вы хотите два значения в одном случае, KeyValuePair <> является достойным заменителем, хотя и неуклюжим. Вы также можете создать структуру или класс, которые будут делать то же самое, и могут расширяться.

12

На мой взгляд, функция анонимных типов не является кортежем, а очень похожей конструкцией. Вывод некоторых запросов LINQ представляет собой коллекции анонимных типов, которые ведут себя как кортежи.

Вот заявление, которое создает типизированный кортеж :-) на лету:

var p1 = new {a = "A", b = 3}; 

см: http://www.developer.com/net/csharp/article.php/3589916

3

C# поддерживает простые кортежи через генериков довольно легко (как на более ранний ответ) , и с помощью «mumble typing» (одного из многих возможных улучшений языка C#), чтобы улучшить вывод типа, они могут быть очень и очень мощными.

Для чего это стоит, F # поддерживает кортежи изначально, и поиграв с ним, я не уверен, что (анонимно) кортежи добавить много ... то, что вы получаете в краткости вы теряете очень быстро в коде ясности ,

Для кода в рамках одного метода существуют анонимные типы; для кода, выходящего за пределы метода, я думаю, что буду придерживаться простых именованных типов. Конечно, если будущий C# упростит сделать эти неизменные (в то время как все еще легко работать), я буду счастлив.

14

Внедрение классов классов или повторное использование классов F # в C# - это только половина истории - это дает вам возможность создавать кортежи с относительной легкостью, но на самом деле не синтаксический сахар, который делает их настолько хорошими для использования на таких языках, как F #.

Например, в F # вы можете использовать шаблон, соответствующий извлечь обе части кортежа в позволении даного, например

let (a, b) = someTupleFunc 

К сожалению, сделать то же самое, используя F # классы из C# было бы гораздо менее элегантно:

Tuple<int,int> x = someTupleFunc(); 
int a = x.get_Item1(); 
int b = x.get_Item2(); 

кортежей представляют собой мощный метод для возвращения нескольких значений из функции без необходимости засорять ваш код с бросовыми классами, или прибегая к уродливым иому или из параметров.Однако, на мой взгляд, без синтаксического сахара, чтобы сделать их создание и доступ к более элегантным, они имеют ограниченное применение.

0

Чтобы сделать их полезными в хэш-таблице или словаре, вы, скорее всего, захотите предоставить перегрузки для GetHashCode и Equals.

2

Вот мой набор кортежей, они автоматически сгенерирован с помощью скрипта Python, так что я, возможно, пошел немного за борт:

Link to Subversion repository

Вам потребуется имя пользователя/пароль, они как гость

они основаны на наследстве, но 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 
15

Существует собственно (не быстро) C# Кортеж реализация в Lokad Shared Libraries (с открытым исходным кодом, конечно) который включает следующие обязательные функции:

  • 2-5 неизменных реализации кортежа
  • Правильного DebuggerDisplayAttribute
  • Собственных хэшировании и равенство проверяет
  • Helpers для генерации кортежей из предоставленных параметров (дженерик выведенных компилятора) и расширений для операций по сбору основы.
  • производства-протестированы.
3

Мой открытым исходный код .NET Sasa library был кортежи в течение многих лет (наряду с большим количеством других функций, как полный MIME разборе). Я использую его в производственном кодексе в течение нескольких лет.

3

C# 7 поддерживает кортежи нативно:

var unnamedTuple = ("Peter", 29); 
var namedTuple = (Name: "Peter", Age: 29); 
(string Name, double Age) typedTuple = ("Peter", 29); 
Смежные вопросы