57

I can't figure out the syntax to do inline collection initialization for:

var a = new List<KeyValuePair<string, string>>();
user7116
  • 63,008
  • 17
  • 141
  • 172
loyalflow
  • 14,275
  • 27
  • 107
  • 168

5 Answers5

93

Note that the dictionary collection initialization { { key1, value1 }, { key2, value2 } } depends on the Dictionary's Add(TKey, TValue) method. You can't use this syntax with the list because it lacks that method, but you could make a subclass with the method:

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

public class Program
{
    public static void Main()
    {
        var list = new KeyValueList<string, string>
                   {
                       { "key1", "value1" },
                       { "key2", "value2" },
                       { "key3", "value3" },
                   };
    }
}
phoog
  • 42,068
  • 6
  • 79
  • 117
  • 8
    +1 for describing exactly what the dictionary initializer sugar translates to. – Shibumi May 09 '13 at 18:00
  • You might want make that 'base.Add' because as I understand C# you're simply calling the Add method of the `KeyValueList` object you've defined. – Richard Barker Oct 14 '16 at 03:35
  • @RichardBarker you are correct that `base.Add` would be less ambiguous. I prefer as a matter of style to avoid `base.` and `this.` unless they are necessary, because in my view they just create so much clutter. But others disagree, and those people would indeed want to use the `base.` keyword. – phoog Oct 14 '16 at 03:43
89

Pretty straightforward:

var a = new List<KeyValuePair<string, string>>()
{
    new KeyValuePair<string, string>("A","B"),
    new KeyValuePair<string, string>("A","B"),
    new KeyValuePair<string, string>("A","B"),
};

Note that you can leave the trailing comma after the last element (probably because .net creators wanted to make automatic code-generation easier), or remove the () brackets of the list contructor and the code still compiles.

digEmAll
  • 56,430
  • 9
  • 115
  • 140
13

Another alternative that doesn't require making a subclass:

List<KeyValuePair<String, String>> list = new Dictionary<String, String>
    {
        {"key1", "value1"},
        {"key2", "value2"},
    }.ToList();

As mentioned in the comments: drawbacks with this method include possible loss of ordering and inability to add duplicate keys.

elRobbo
  • 613
  • 7
  • 10
  • 1
    hmm.. this might not preserve the ordering you have specified in your initializer, but i am not exactly sure. maybe you can initialize a sorted list and then convert ToList? – Can Bud Sep 07 '15 at 11:47
  • 3
    You also cannot store duplicate entries like this. One of the reasons for using List... – ComeIn Feb 05 '17 at 23:51
  • 1
    It also involves hashing all the keys and a lot more allocations. – Edward Brey Mar 01 '18 at 12:46
10

Since collection initializers (C# 6.0) have not been mentioned here:

Implementation

public static class InitializerExtensions
{
   public static void Add<T1, T2>(this ICollection<KeyValuePair<T1, T2>> target, T1 item1, T2 item2)
   {
       if (target == null)
            throw new ArgumentNullException(nameof(target));

        target.Add(new KeyValuePair<T1, T2>(item1, item2));
    }
}

Usage

var list = new List<KeyValuePair<string, string>> { {"ele1item1", "ele1item2"}, { "ele2item1", "ele2item2" } };

How to make it work

Just include the right using statements in your file so that InitializerExtensions is available (meaning you could call InitializerExtensions.Add explicitly) and the special collection initializer syntax will become available if you are using VS 2015 or higher.

user764754
  • 3,865
  • 2
  • 39
  • 55
  • 1
    This extension must be a built-in part of C#, why we can use compact initilaizers for `Dictionary` but not `List` ?! – S.Serpooshan Jun 04 '23 at 19:21
-1

Any initialization is done by object(params_if_exist) { any public member or instance};

f.e. var list = new List<int> {1,2,3};

var bw = new BackgroundWorker() {WorkerSupportsCancellation = true};

burning_LEGION
  • 13,246
  • 8
  • 40
  • 52
  • 3
    This does not answer the OPs question. The OP is looking for collection initialization specifically for KeyValue pairs. – Stefan H Jul 27 '12 at 20:10
  • i think that he must understand as it work, but not use ready solution, and ask again and again same question – burning_LEGION Jul 27 '12 at 20:12
  • Which "public member or instance" is set by `1,2,3` in your first example? – phoog Jul 27 '12 at 20:13
  • @phoog I think that it is syntactic sugar for grabbing the Add(T) method of the list, same applies with all collections, that's why digEmAll's solution works – Stefan H Jul 27 '12 at 20:14
  • @StefanH you are correct. I was trying to point out *why* the answer "does not answer the OP's question", as you said, because "any public member or instance" is not an adequate description of initialization: it describes object initializers, but not collection initializers. – phoog Jul 27 '12 at 21:02