Подтвердить что ты не робот

Каков наилучший способ использования пары (тройной и т.д.) Значений как одно значение в С#?

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

Вариант использования на мой взгляд:

Dictionary<Pair<string, int>, object>

или

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

Существуют ли встроенные типы, такие как Pair или Triple? Или какой лучший способ его реализации?

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

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

4b9b3361

Ответ 2

Встроенные классы

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

Пары и тройки

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

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

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

Корреспонденты более высокого порядка

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

Если вы установили F # language, вы можете ссылаться на файл 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>();

Сверните свой собственный

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

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

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; }
    }
}

Рамки и библиотеки

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

Ответ 3

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;
}

Ответ 4

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

Ответ 5

Пара и триплет - это существующие классы в .net, см. msdn:

Triplet

Pair

Я недавно наткнулся на них, играя с расширением viewstate

Ответ 6

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

Ответ 7

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>();

Примечание. В System.Web -dll существуют классы Триплет и Пара, поэтому он не очень подходит для других решений, чем ASP.NET.

Ответ 8

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

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

Предполагая, что это не является проблемой для вас, все еще существует проблема, из-за которой трудно найти код:

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?

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

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

var retVal = GetSomething();

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

Ответ 9

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

Ответ 10

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

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

Ответ 11

Нет встроенных вложений, но класс Pair < T, R > тривиален для создания.

Ответ 12

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

Ответ 13

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

Dictionary<KeyValuePair<string, int>, object>

Ответ 14

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

Ответ 15

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

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

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.

Ответ 16

В F # также есть типы Tuple < > ; вам просто нужно ссылаться на файл FSharp.Core.dll.