11

Simple. If I use:

public void Add(params int[] values) 

Then I can use this as:

Add(1, 2, 3, 4); 

But now I'm dealing with key-value pairs! I have a KeyValue class to link an integer to a string value. So I start with:

public void Add(params KeyValue[] values) 

But I can't use this:

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

Instead, I'm forced to use:

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

Ewww... Already I dislike this...

So, right now I use the Add function without the params modifier and just pass a pre-defined array to this function. Since it's just used for a quick initialization for a test, I'm not too much troubled about needing this additional code, although I want to keep the code simple to read. I would love to know a trick to use the method I can't use but is there any way to do this without using the "new KeyValue()" construction?

2
  • 7
    You know there's already a KeyValuePair<TKey, TValue>? Commented Sep 1, 2009 at 12:56
  • Yeah, I know. :-) It's the type I use... Commented Sep 1, 2009 at 14:41

3 Answers 3

23

If you accepted an IDictionary<int,string>, you could presumably use (in C# 3.0, at least):

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

Any use?

Example Add:

static void Add(IDictionary<int, string> data) { foreach (var pair in data) { Console.WriteLine(pair.Key + " = " + pair.Value); } } 
Sign up to request clarification or add additional context in comments.

1 Comment

You can also use type aliasing if you don't want to type out the whole generic Dictionary type using Pairs = System.Collections.Generic.Dictionary<int, string>; and then use as Add(new Pairs { {1, "A"}, {2, "B"}, {3, "C"}, {4, "D"} }); slightly neater.
3

You can modify your current class design, but you will need to add generics and use the IEnumerable interface.

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

After these additions you can do the following:

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

The compiler will use the IEnumerable interface and the Add method to populate the KeyValueList. Note that it works for C# 3.0.

If you are using this for tests, these changes are not worth it. It's quite an effort and you change quite a lot of production code for tests.

2 Comments

Inheriting from List<KeyValue<TKey, TValue>> and adding the custom Add would be the easiest route here.
@Marc: Good idea. Haven't thought of that.
0

You could use something like the following with the obvious drawback that you loose strong typing.

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

You should of cause add some error handling if the arguments are of incorrect type. Not that smart, but it will work.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.