2009-09-01 2 views
10

Простой. Если я использую:Использование пар ключ-значение в качестве параметров

public void Add(params int[] values) 

Тогда я могу использовать это как:

Add(1, 2, 3, 4); 

Но теперь я имею дело с парами ключ-значение! У меня есть класс KeyValue, который связывает целое число со строковым значением. Поэтому я начинаю с:

public void Add(params KeyValue[] values) 

Но я не могу использовать это:

Add(1, "A", 2, "B", 3, "C", 4, "D"); 

Вместо этого, я вынужден использовать:

Add(new KeyValue(1, "A"), new KeyValue(2, "B"), new KeyValue(3, "C"), new KeyValue(4, "D")); 

Ewww ... Я уже не нравится это ...

Итак, прямо сейчас я использую функцию Add без модификатора params и просто передаю предварительно заданный массив этой функции. Поскольку он просто используется для быстрой инициализации теста, я не слишком беспокоюсь о необходимости использования этого дополнительного кода, хотя я хочу, чтобы код был прост для чтения. Я хотел бы знать трюк, чтобы использовать метод, который я не могу использовать, но есть ли способ сделать это без использования «новой конструкции KeyValue()»?

+7

Вы знаете, что уже существует «KeyValuePair »? –

+0

Да, я знаю. :-) Это тип, который я использую ... –

ответ

23

Если вы приняли IDictionary<int,string>, вы могли бы предположительно использовать (в C# 3.0, по крайней мере):

Add(new Dictionary<int,string> { 
    {1, "A"}, {2, "B"}, {3, "C"}, {4, "D"} 
}); 

Любое использование?

Пример Add:

static void Add(IDictionary<int, string> data) { 
    foreach (var pair in data) { 
     Console.WriteLine(pair.Key + " = " + pair.Value); 
    } 
} 
+0

Выглядит хорошо! Он держит вещи в одной строке. –

+0

Вы также можете использовать наложение типов, если вы не хотите вводить весь общий тип словаря 'using Pairs = System.Collections.Generic.Dictionary ;', а затем использовать как 'Add (new Pairs { {1," A "}, {2," B "}, {3," C "}, {4," D "} });' немного опрятно. –

0

Вы могли бы использовать что-то вроде следующего с очевидным недостатком, что вы теряете строгую типизацию.

public void Add(params Object[] inputs) 
{ 
    Int32 numberPairs = inputs.Length/2; 

    KeyValue[] keyValues = new KeyValue[numberPairs]; 

    for (Int32 i = 0; i < numberPairs; i++) 
    { 
     Int32 key = (Int32)inputs[2 * i]; 
     String value = (String)inputs[2 * i + 1]; 

     keyvalues[i] = new KeyValue(key, value); 
    } 

    // Call the overloaded method accepting KeyValue[]. 
    this.Add(keyValues); 
} 

public void Add(params KeyValue[] values) 
{ 
    // Do work here. 
} 

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

3

Вы можете изменить текущий дизайн вашего класса, но вам нужно будет добавить дженерики и использовать интерфейс IEnumerable.

class KeyValue<TKey, TValue> 
    { 
     public KeyValue() 
     { 
     } 
    } 

    // 1. change: need to implement IEnumerable interface 
    class KeyValueList<TKey, TValue> : IEnumerable<TKey> 
    { 
     // 2. prerequisite: parameterless constructor needed 
     public KeyValueList() 
     { 
      // ... 
     } 

     // 3. need Add method to take advantage of 
     // so called "collection initializers" 
     public void Add(TKey key, TValue value) 
     { 
      // here you will need to initalize the 
      // KeyValue object and add it 
     } 

     // need to implement IEnumerable<TKey> here! 
    } 

После этих дополнений вы можете сделать следующее:

new KeyValueList<int, string>() { { 1, "A" }, { 2, "B" } }; 

компилятор будет использовать IEnumerable интерфейс и метод Add, чтобы заселить KeyValueList. Обратите внимание, что он работает для C# 3.0.

Если вы используете это для тестов, эти изменения не стоят того. Это довольно много усилий, и вы меняете довольно много производственного кода для тестов.

+1

Унаследовано от 'List >' и добавление пользовательского 'Add' будет самым простым путем здесь. –

+0

@Marc: Хорошая идея. Не думал об этом. –

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