2011-01-26 5 views
1

Почему .NET не предоставляет класс для List<KeyValuePair<T, U>>?Список KeyValuePair

Я думаю, что существует много ситуаций, когда вам нужно держать массив пар. Например,

1; 2  "a"; "array" 
5; 8  "b"; "browser" 
1; 9  "f"; "Firefox" 
8; 10  "f"; "frequency" 

а-ля:

Pairs<int, int> myPairs; 

myPairs.Add(10, 8); 
myPairs.Add(5, 8); 
myPairs.Add(10, 5); 
myPairs.Add(1, 4); 

myPairs[0].Value1 = 5; 
myPairs[5].Value2 = 8; 
+6

... почему бы просто не использовать 'List >'? – Mehrdad

+1

@Mehrdad: немного «сложно» его построить.- Я имею в виду, что вы должны закодировать небольшой строительный ключValuePairs, а затем объединить их в список. Наконец, почему был создан список ? Вы можете использовать Массивы! :) – serhio

+1

Это проще в использовании Tuple, чем KeyValuePair - и более подходящее тоже. –

ответ

1

Вы можете искать Dictionary<TKey,TValue>:

Представляет коллекцию ключей и значений.

Dictionary<TKey,TValue> - специализированная коллекция, оптимизированная для пар ключ/значение. Хотя вы можете создавать List<KeyValuePair<TKey,TValue>>, вы меняете себя, так как у вас не будет оптимизированного доступа к вашим ключам.

+2

нет. Единственное ограничение. – serhio

+0

А, хороший момент - сначала это не поймало. –

3

Что вам мешает использовать List<KeyValuePair<T, V>>? И, если вы знаете T и V, вы можете его псевдоним в верхней части исходного файла:

using KeyValueList = System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<MyNS.MyKeyType, MyNS.MyValueType>>; 

// in your code... 
KeyValueList list = new KeyValueList(); 
list.Add(new KeyValuePair<MyKeyType, MyValueType>(..., ...)); 
+1

см. Ответ на замечание. Почему был создан список ? Вы можете использовать Массивы! :) – serhio

+1

и, наконец, вопрос не в том, что я не могу использовать, но почему нет более «comode» класса. – serhio

+1

'list.Add (новый KeyValuePair (..., ...));' не так красиво. а в VB.NET хуже, чем. – serhio

4

зачем останавливаться? Почему не список триплетов? Или квадруплеты?

Дело в том, что это очень тривиально написать себе. Напишите класс, который происходит от List<KeyValuePair<TKey, TValue>>, добавьте метод Add, который принимает 2 параметра.

public class KeyValueList<TKey, TValue> : List<KeyValuePair<TKey, TValue>> 
{ 
    public void Add(TKey key, TValue value) 
    { 
     Add(new KeyValuePair<TKey, TValue>(key, value)); 
    } 
} 

Бум, все готово.


Дополнительные замечания: Обратите внимание, что KeyValuePair<TKey, TValue> непреложный типа (как в .NET 4.0 Tuple<T1, T2>); так что если вы хотите, чтобы иметь возможность сделать что-то вроде этого:

list[0].Value = 5; 

... тогда вам нужен изменяемый тип, что-то вроде:

public sealed class Pair<T1, T2> 
{ 
    public T1 X { get; set; } 
    public T2 Y { get; set; } 
} 

public class PairList<T1, T2> : List<Pair<T1, T2>> 
{ /* ...same as KeyValueList<T1, T2>, basically... */ } 

Также обратите внимание, что это позволило бы хороший синтаксис инициализации:

var list = new PairList<int, string> 
{ 
    { 1, "dan" }, 
    { 2, "serhio" } 
}; 

Но снова, дело здесь в том, что это очень легко и очень тривиальна и, таким образом, на самом деле не заслуживает своего собственного типа в рамках , Посмотрите на это так: можете ли вы назвать любой тип в BCL, который по существу является только еще одним номером, но с добавлением одного удобного метода?


Закрыв комментарии: Вы поставили эти вопросы:

  • Зачем использовать List<T> тип, когда вы могли бы просто использовать T[] массив?
  • Зачем вводить тип Dictionary<TKey, TValue>, если вы могли бы просто использовать List<KeyValuePair<TKey, TValue>>?

Это странные вопросы, честно говоря. Зачем вообще вводить ООП, когда вы можете просто делать все с процедурным кодом и глобальными переменными? Зачем вводить языки программирования более высокого уровня, такие как C#, C++ или даже C, когда вы могли бы просто написать все в Assembly?

List<T> класс обеспечивает полезный инкапсуляцию всей функциональности, которая входит в доступе к элементам массива, сохраняя количество элементов, изменение размера массива по мере необходимости, и т.д. Существует большая разница между тем, что вас может делать с List<T> и что вы можете сделать только с T[].

Dictionary<TKey, TValue> также включает в себя функции сохранения коллекции значений, связанных с уникальными ключами. Он также обеспечивает время поиска O (1) для этих ключей. Существует огромная разница между Dictionary<TKey, TValue> и List<KeyValuePair<TKey, TValue>>.

Разница между List<KeyValuePair<TKey, TValue>> и предложенными вами KeyValueList<TKey, TValue> (как я уже назвал выше) практически равна нулю. Вряд ли что-то новое инкапсулировано. Это только is a List<T>. Честно говоря, для меня это выгодно, чуть больше, чем добавление типа Int32List, который просто обертывает List<int>.

Просто нет причин добавлять такой тип к BCL.

+1

довольно тривиально, чтобы написать словарь yoursef. Однако этот класс существует в .NET. – serhio

+3

@serhio: Вы считаете, что для правильного и эффективного использования словаря тривиально? Позволю себе не согласиться. –

+1

и триплеты не так часто используются. Часто задается вопрос о многоязычном словаре, но только в .NET 3.5 появляется класс LookUp. – serhio

9

Это кажется мне совершенно ненужным - и только потому, что у вас есть пара значений, это не значит, что это обязательно отношение ключ/значение.

.NET 4 представил Tuple семейство типов ... если это действительно был пару ключ/значение, я хотел бы использовать вместо List<Tuple<T1, T2>> - и я не вижу никаких оснований для одного типа существовать для того, чтобы инкапсулировать эта конструкция.

EDIT: Для того, чтобы поместить это в контекст, вот как «трудно» это использовать Tuple здесь, превращая ваш пример кода:

var myPairs = new List<Tuple<int, int>> { 
    Tuple.Create(10, 8), 
    Tuple.Create(5, 8), 
    Tuple.Create(10, 5), 
    Tuple.Create(1, 4), 
}; 

Теперь кортежи неизменны, так что вы не смогли бы установить значения непосредственно в соответствии с последней частью вашего кода ... но красота , составляющая, две концепции «списка» и «пары значений» - это то, что вы можете легко написать свой собственный тип MutableTuple и использовать точно такой же код ... тогда как если бы у вас был один класс коллекции, который был жестко связан с Tuple или другим типом, у вас не было бы такой гибкости.

+0

Да, нет необходимости иметь связь между значениями. См. Раздел edit в качестве примера. Вы также можете использовать 'Pairs ' или что угодно. – serhio

+0

@serhio: В этом случае вы не хотите KeyValuePair, но 'List >' должно быть хорошо для вас. –

+0

ваш пример будет немного менее «красивым» при добавлении элементов в foreach в такой структуре или изменении его значений. – serhio

0

Вы можете использовать System.Collections.Specialized.NameValueCollection, это KeyValue магазин;)

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

Или создайте подкласс System.Collections.Specialized.NameObjectCollectionBase для специального решения для вашего типа объекта.

+0

NameValueCollection не является общим. Не используйте метод Add. – serhio

+0

Нет, но потом, как только вы идете с дженериками, существует бесконечное количество возможностей. У меня так много разных комбинаций списка в моем коде, что специальный для Key Value фактически просто усложнил бы все, лучше иметь данное решение, которое работает для всех. –

+0

не понимаю пункт. Объем дженериков заключается в том, чтобы уменьшить ваши «возможности» в одном классе: 'Pairs ' (см. Пример в моей редакции) – serhio

Смежные вопросы