Вопрос по c#, generics – Как лучше всего использовать пару (тройку и т. Д.) Значений в качестве одного значения в C #?

20

То есть я хотел бы иметь кортеж значений.

Случай использования на мой взгляд:

<code>Dictionary<Pair<string, int>, object>
</code>

или же

<code>Dictionary<Triple<string, int, int>, object>
</code>

Есть ли встроенные типы, такие как Pair или Triple? Или как лучше всего это реализовать?

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

Update 2 Думаю, стоит также напомнить, что когда вы используете какое-либо значение в качестве ключа в словаре, оно должно быть неизменным.

Ваш Ответ

16   ответов
12
public struct Pair<T1, T2>
{
    public T1 First;
    public T2 Second;
}

public struct Triple<T1, T2, T3>
{
    public T1 First;
    public T2 Second;
    public T3 Third;
}
2

Вы можете относительно легко создавать свои собственные классы кортежей, единственное, что потенциально может привести к путанице, - это равенство и переопределение хэш-кода (важно, если вы собираетесь использовать их в словарях).

Следует отметить, что .NetKeyValuePair<TKey,TValue> структура имеетотносительно медленные методы равенства и хэш-кода.

Если предположить, что вас это не беспокоит, проблема в том, что код в конечном итоге будет трудно выяснить, по-прежнему остается проблемой:

public Tuple<int, string, int> GetSomething() 
{
    //do stuff to get your multi-value return
}

//then call it:
var retVal = GetSomething();

//problem is what does this mean?
retVal.Item1 / retVal.Item3; 
//what are item 1 and 3?

В большинстве этих случаев мне проще создать определенный класс записей (по крайней мере, пока C # 4 не сделает это волшебством компилятора)

class CustomRetVal {
    int CurrentIndex { get; set; }
    string Message { get; set; }
    int CurrentTotal { get; set; }
}

var retVal = GetSomething();

//get % progress
retVal.CurrentIndex / retVal.CurrentTotal;
2

KeyValuePair это лучший класс для расширения, если вы не хотите создавать свои собственные классы.

int id = 33;
string description = "This is a custom solution";
DateTime created = DateTime.Now;

KeyValuePair<int, KeyValuePair<string, DateTime>> triple =
   new KeyValuePair<int, KeyValuePair<string, DateTime>>();
triple.Key = id;
triple.Value.Key = description;
triple.Value.Value = created;

Вы можете расширить его на столько уровней, сколько захотите.

KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string, string> quadruple =
   new KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string, string>();

Note: КлассыTriplet а такжеPair существует внутриSystem.Web-dll, так что он не очень подходит для других решений, кроме ASP.NET.

11

Перемотка вперед к 2010 году. NET 4.0 теперь поддерживаетn-кортежей произвольного n, Эти кортежи реализуют структурное равенство и сравнение, как и ожидалось.

2

Одно простое решение еще не было упомянуто. Вы также можете просто использоватьList<T>, Он встроен, эффективен и прост в использовании. Конечно, поначалу это выглядит немного странно, но отлично справляется со своей задачей, особенно для большого количества элементов.

0

Вы можете использовать System.Collections.Generic.KeyValuePair в качестве вашей реализации Pair.

Или вы можете просто реализовать свои собственные, это не сложно:

public class Triple<T, U, V>
{
  public T First {get;set;}
  public U Second {get;set;}
  public V Third {get;set;}
}

Конечно, вы можете когда-нибудь столкнуться с проблемой, что Triple (string, int, int) не совместима с Triple (int, int, string). Возможно, вместо этого используйте System.Xml.Linq.XElement.

Эта реализация неверна. Смотрите ссылку в вопросе. Если вы используете класс для кортежа, вы не можете использовать его как ключ в словаре, потому что, если вы не переопределите GetHashCode () Max Galkin
0

Для этого нет встроенных классов. Ты можешь использоватьKeyValuePair или разверните свою собственную реализацию.

3

Я обычно просто создаю свою собственную структуру, содержащую значения. Это часто более читабельно;)

6

Я реализовал библиотеку кортежей в C #. Визитhttp://www.adventuresinsoftware.com/generics/ и нажмите на «кортежи»; ссылка на сайт.

И мне нравится "Sextuple" учебный класс ;-) Max Galkin
Да, это, кажется, довольно хорошая реализация. Не могли бы вы опубликовать свой код для класса Tuple здесь? Мне также кажется, что существует возможность переполнения в вашей функции GetHashCode (), не так ли? Max Galkin
Извините, у меня недостаточно символов для размещения кода здесь. Я должен поставить "непроверенный" на метод GetHashCode. Хороший улов.
Ну, может быть, несколько сокращенную версию, чтобы привести быстрый пример? .. Э-э, без ToString () ... Что касается GetHashCode (), я хотел бы использовать модуль calc (%), но тогда ваша идея кажется лучше: нам просто нужно "немного" как можно быстрее. Max Galkin
9

Pair и Triplet - это существующие классы в .net, см. Msdn:

Триплет

пара

Я недавно сталкивался с ними, играя с декодированием представления состояния

1. Они есть в Web.UI :-) 2. Они не являются общими 3. А как насчет GetHashCode? Max Galkin
Я большой поклонник Triplet при динамическом добавлении элементов управления на веб-страницу.
3. Если они не переопределяют GetHashCode () и Equals (), вы не можете использовать их для ключей в коллекциях. Смотрите ссылку в вопросе. Max Galkin
1, Да, как я уже сказал, я видел, что это используется на сайте asp.net, поэтому я подумал, что упомяну это. 2, это снова верно, если вам нужно что-то общее, я бы пошел с решением yshuditelu 3, как насчет этого?
20

Builtin Classes

В некоторых конкретных случаях .net Framework уже предоставляет классы, подобные кортежу, которые вы можете использовать.

Pairs and Triples

Универсальный System.Collections.Generic.KeyValuePair класс может быть использован как реализация пары adhoc. Это класс, который Общий словарь использует внутренне.

Кроме того, вы можете обойтись с System.Collections.DictionaryEntry структура, которая действует как элементарная пара и имеет преимущество быть доступным в Mscorlib. С другой стороны, это то, что эта структура не строго типизированный.

Пары и тройки также доступны в виде System.Web.UI.Pair а также System.Web.UI.Triplet классы. Несмотря на то, что эти классы живут вSystem.Web сборка они могли бы быть идеально подходящими для разработки формы win. Тем не менее, эти классы также не является строго типизированным и может не подходить для некоторых сценариев, таких как универсальная структура или библиотека.

Higher order tuples

Для кортежей более высокого порядка, если не считать собственного класса, возможно не будет простым решением.

Если вы установили Язык F #Вы могли бы сослаться наFSharp.Core.dll который содержит набор универсальных неизменяемых Microsoft.Fsharp.Core.Tuple классы до общего числа. Тем не менее, даже при неизменномFSharp.Code.dll может быть распространен, F # является исследовательским языком и незавершенным Это решение, вероятно, будет представлять интерес только в академических кругах.

Если вы не хотите создавать свой собственный класс и вам неудобно ссылаясь на библиотеку F #, один изящный трюк может заключаться в расширении универсального класса KeyValuePair, так что элемент Value сам по себе является вложенным KeyValuePair.

Например, следующий код иллюстрирует, как вы можете использовать KeyValuePair для создания тройки:

int id = 33;
string description = "This is a custom solution";
DateTime created = DateTime.Now;

KeyValuePair<int, KeyValuePair<string, DateTime>> triple =
   new KeyValuePair<int, KeyValuePair<string, DateTime>>();
triple.Key = id;
triple.Value.Key = description;
triple.Value.Value = created;

Это позволяет расширить класс до любого произвольного уровня, как требуется.

KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string>, string> quadruple =
    new KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string>, string>();
KeyValuePair<KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string>, string>, string> quintuple =
    new KeyValuePair<KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string>, string>, string>();

Roll Your Own

В других случаях вам, возможно, придется прибегнуть к класс кортежа, и это не сложно.

Вы можете создавать простые структуры, такие как:

struct Pair<T, R>
{
    private T first_;
    private R second_;

    public T First
    {
        get { return first_; }
        set { first_ = value; }
    }

    public R Second
    {
        get { return second_; }
        set { second_ = value; }
    }
}

Frameworks and Libraries

Эта проблема была решена ранее и общие рамки существуют Ниже приведена ссылка на один из таких фреймворков:

Библиотека .NET 4.0, которая в настоящее время находится в бета-версии, также включает в себя кортежи.
Отличная сводка всех доступных методов.
0

Для первого случая я обычно использую

Dictionary<KeyValuePair<string, int>, object>
0

Здесь нет встроенных модулей, но есть пара & lt; T, R & gt; класс тривиально создать.

0

Да, есть System.Web.UI.Pair и System.Web.UI.Triplet (у которого есть перегруженный создатель для парного поведения!)

1

NGenerics - популярная библиотека .Net алгоритмов и структур данных, недавно представилаimmutable структуры данных на множество.

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

0

Есть также Tuple & lt; & gt; вводит в F #; вам просто нужно сослаться на FSharp.Core.dll.

Похожие вопросы