То есть я хотел бы иметь кортеж значений.
Вариант использования на мой взгляд:
Dictionary<Pair<string, int>, object>
или же
Dictionary<Triple<string, int, int>, object>
Есть ли встроенные типы, такие как Pair или Triple? Или как лучше всего это реализовать?
Обновлять В ответах описаны некоторые универсальные реализации кортежей, но для кортежей, используемых в качестве ключей в словарях, вы должны дополнительно проверить правильность вычисления хэш-кода. Подробнее об этом в другом вопрос.
Обновление 2 Думаю, также стоит напомнить, что когда вы используете какое-то значение в качестве ключа в словаре, оно должно быть неизменным.





Обычно я просто создаю свою собственную структуру, содержащую значения. Часто это немного читабельнее;)
Встроенных модулей нет, но создать класс Pair <T, R> несложно.
Pair и Triplet - это существующие классы в .net, см. Msdn:
Я недавно столкнулся с ними, играя с декодированием состояния просмотра
Я большой поклонник Triplet при динамическом добавлении элементов управления на веб-страницу.
1, Да, они есть, как я уже сказал, я видел, что это используется на сайте asp.net, поэтому я подумал, что упомяну об этом. 2, это снова правда, если вам нужно что-то общее, я бы пошел с решением yshuditelu 3, что насчет этого?
3. Если они не отменяют GetHashCode () и Equals (), вы не можете использовать их для ключей в коллекциях. См. Ссылку в вопросе.
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;
}
Да, есть System.Web.UI.Pair и System.Web.UI.Triplet (у которого есть перегруженный создатель для поведения типа Pair!)
В первом случае я обычно использую
Dictionary<KeyValuePair<string, int>, object>
Для этого нет встроенных классов. Вы можете использовать KeyValuePair или развернуть свою собственную реализацию.
Вы можете использовать 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 ()
Я реализовал библиотеку кортежей на C#. Посетите http://www.adventuresinsoftware.com/generics/ и щелкните ссылку "кортежи".
Да, вроде бы неплохая реализация. Не могли бы вы разместить здесь свой код для класса Tuple? Мне также кажется, что в вашей функции GetHashCode () есть возможность переполнения, не так ли?
А еще мне нравится класс "Sextuple" ;-)
Извините, у меня недостаточно символов, чтобы разместить здесь код. Я должен поставить «не отмечен» на метод GetHashCode. Хороший улов.
Ну, может быть, несколько сокращенная версия, чтобы дать быстрый пример? .. Эээ, без ToString () ... Что касается GetHashCode (), я хотел бы использовать модуль calc (%), но тогда ваша идея кажется лучше: нам просто нужно "some" int как можно быстрее.
В F# также есть типы Tuple <>; вам просто нужно сослаться на FSharp.Core.dll.
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.
В некоторых конкретных случаях инфраструктура .net уже предоставляет классы, похожие на кортежи, которые вы можете использовать.
Пары и тройки
Общий System.Collections.Generic.KeyValuePair class может использоваться как реализация специальной пары. Это класс, который Общий словарь используется для внутренних целей.
В качестве альтернативы вы можете обойтись System.Collections.DictionaryEntry структура, которая действует как рудиментарная пара и имеет преимущество доступны в mscorlib. С другой стороны, однако, эта структура не строго типизированный.
Пары и тройки также доступны в виде System.Web.UI.Pair и System.Web.UI.Triplet классы. Хотя эти классы живут в сборке System.Web они могут идеально подходить для разработки winforms. Однако эти классы также не является строго типизированным и может не подходить в некоторых сценариях, например в универсальной платформе или библиотеке.
Кортежи высшего порядка
Для кортежей более высокого порядка, за исключением катания вашего собственного класса, может не будет простым решением.
Если вы установили 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>();
В других случаях вам, возможно, придется прибегнуть к прокрутке собственного класс кортежа, и это несложно.
Вы можете создавать такие простые структуры:
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; }
}
}
Эта проблема уже решалась, и фреймворки общего назначения существуют. Ниже приведена ссылка на один из таких фреймворков:
Отличное резюме всех доступных методов.
Библиотека .NET 4.0, которая в настоящее время находится в стадии бета-тестирования, также включает кортежи.
Вы можете относительно легко создавать свои собственные классы кортежей, единственное, что потенциально может стать беспорядочным, - это ваше равенство и переопределения хэш-кода (важно, если вы собираетесь использовать их в словарях).
Следует отметить, что собственная структура KeyValuePair<TKey,TValue> .Net имеет относительно медленные методы равенства и хэш-кода.
Предполагая, что вас это не беспокоит, все еще существует проблема, заключающаяся в том, что код оказывается трудным для понимания:
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;
NGenerics - популярная библиотека алгоритмов и структур данных .Net, недавно добавила в набор структуры данных неизменный.
Первыми неизменяемыми из них были реализованы классы пара и кортеж. Код хорошо покрыт тестами и довольно элегантен. Вы можете проверить это здесь. В настоящее время они работают над другими неизменными альтернативами, и они должны быть готовы в ближайшее время.
Одно простое решение еще не упоминалось. Вы также можете просто использовать List<T>. Он встроен, эффективен и прост в использовании. Конечно, сначала это выглядит немного странно, но свою работу выполняет отлично, особенно для большего количества элементов.
Перенесемся в 2010 год: .NET 4.0 теперь поддерживает n наборов произвольных n. Эти кортежи реализуют структурное равенство и сравнение, как и ожидалось.
1. Они находятся в Web.UI :-) 2. Они не являются общими 3. А как насчет GetHashCode?