Как лучше всего использовать пару (тройку и т. д.) значений как одно значение в C#?

StackOverflow https://stackoverflow.com/questions/101825

Вопрос

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

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

Dictionary<Pair<string, int>, object>

или

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

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

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

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

Это было полезно?

Решение

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

Другие советы

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

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

Пары и тройки

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

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

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

Кортежи высшего порядка

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

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

Если вы не хотите создавать свой собственный класс и вам некомфортно ссылаться на библиотеку F#, один изящный трюк может состоять в расширении общего класса KeyValuePair, чтобы участник стоимости сам по себе является вложенным 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>();

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

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

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

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

Фреймворки и библиотеки

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

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

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

Pair и Triplet — существующие классы в .net, см. msdn:

Триплет

Пара

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

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

КлючЗначениеПара — лучший класс для расширения, если вы не хотите создавать свои собственные классы.

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

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

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

Следует отметить, что собственная KeyValuePair<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;

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

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

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

Встроенных модулей нет, но создать класс Pair<T,R> тривиально.

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

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

Dictionary<KeyValuePair<string, int>, object>

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

Вы можете использовать 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.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top