13

Here's a question that I always come back too every so often:

What's the best <string, string> Collection to use, for some xyz situation (most often to bind to a DropDownList) ?

Does anyone have a cheat sheet for this? a comprehensive list of distinctions between the various options?

Julien Roncaglia
  • 17,397
  • 4
  • 57
  • 75
bash_79
  • 173
  • 4
  • Awesome, I am printing this out now! – Jake Kalstad Jul 27 '11 at 21:12
  • 4
    KeyValuePair array is IEnumerable. – Grozz Jul 27 '11 at 21:13
  • Any reason you left out SortedList ? – Ed Bayiates Jul 27 '11 at 21:13
  • 1
    I struggle to find a good reason to use a ListDictionary, it is very short on features and long on limitations. – Eric H Jul 27 '11 at 22:42
  • "KeyValuePair array is IEnumerable. – Grozz" Ok... What are the disadvantages of the Array VS List then? I think there are other interfaces the Array doesn't implement then... – bash_79 Jul 28 '11 at 17:49
  • "Any reason you left out SortedList ? – AresAvatar" Cool - I thought SortedList was only 1 dimension like a standard List..! – bash_79 Jul 28 '11 at 17:52
  • Your description of `ListDictionary` as "faster lookup than the Dictionary" is misleading, if not completely wrong. [`ListDictionary`](http://msdn.microsoft.com/en-us/library/system.collections.specialized.listdictionary.aspx) uses a singly-linked list, so *all* operations are O(n), whereas a `Dictionary` uses a hashtable, where lookup operations are amortized O(1) in the average case. It's true that the list implementation *can* be faster for small collections, but for large collections, the Dictionary will be **many orders of magnitude** faster. – Daniel Pryden Jul 28 '11 at 20:20
  • 1
    Also, **all** .NET arrays implement `IList` and `IList`, and therefore, by extension, `ICollection`, `ICollection`, `IEnumerable` and `IEnumerable`. The biggest disadvantage to using an array instead of another `IList` implementation (like `List`) is that arrays are fixed-size (the `IList.Add()` method on them doesn't work). – Daniel Pryden Jul 28 '11 at 20:24
  • Finally, I'd recommend that you separate your **question** (which is "what are the differences between these different collections?") from your **answer** (which is your "here's the extent of my knowledge on this" section). Because I would like to be able to upvote your question (because it's interesting) but not your answer (because it's wrong). – Daniel Pryden Jul 28 '11 at 20:26
  • Thanks for the feedback @DanielPryden - regarding ListDictionary, you're right, I misquoted some other site :/ ... – bash_79 Jul 29 '11 at 14:14

2 Answers2

5

If you're binding to a dropdown list, you probably have a sort order in mind and the size of the collection will (most likely and in most use cases) be small enough to avoid performance concerns. In these cases, a List<KeyValuePair<string, string>> is a pretty easy choice, although a BindingList might work better for binding, especially in WPF.

Tuple<string, string> can replace KeyValuePair even.

Furthermore, the non-generic (not strong typed) collections often give some of the worst performance with boxing (on top of being unwieldy to work with) and if you're worried about list overhead, you can specify a maximum size on creation to minimize that. Another advantage of the generic classes is that they implement IEnumerable for use with Linq and, in my experience, tend to be more widely used and better known to your colleagues. In general, there should be 1 obvious way to do something in a language and the .Net community has chosen Dictionary<string, string> over StringDictionary.

You can also add extension methods to make basic lists more convenient:

public static class ListKeyValuePairExtensions
{
    public static void Add<S, T>(this List<KeyValuePair<S, T>> list, S key, T value)
    {
        list.Add(new KeyValuePair<S, T>(key, value));
    }
}

Edit: As pointed out by Porges, in cases addressed by this question, the performance hit of non-generic structures is not from boxing and unboxing, there is still a performance hit however, see this article for a quick benchmark.

marr75
  • 5,666
  • 1
  • 27
  • 41
  • 3
    If you're using strings, or especially string-specific classes, there will be no boxing. – porges Jul 27 '11 at 21:23
  • 1
    Well, that's why I added "(not strong typed)". Obviously StringDictionary is strong typed but not generic. Useful to point out in case anyone reads this and is confused, though. – marr75 Jul 27 '11 at 21:27
  • 1
    There will still be no boxing. Reference types are never (and cannot be) boxed. – porges Jul 27 '11 at 21:29
  • Thanks for the feedback. I've used `List>` once in a while for my DropDownLists because it conserves the order that I inserted. But I do not find it's an easy choice... What I would love is a collection that gives me the simplicity of `list.Add("key", "value")` and keeps the same order as inserted... As for the `Tuple`, I'll look into it! – bash_79 Jul 28 '11 at 18:13
  • You could write an extension method for 'List' See my edited answer. – marr75 Jul 28 '11 at 21:07
  • Actually I just discovered `OrderedDictionary` - I think that's the one I'm actually looking for... Although it's not generic... – bash_79 Jul 29 '11 at 15:06
  • I'd go with the generic SortedDictionary instead. – marr75 Jul 30 '11 at 00:51
1

Here's the extent of my knowledge on this:



    StringDictionary strDict = new StringDictionary();
        // + Strong Type
        // - lowercases the key
        // - random order ?
        // - older approach, .Net 1 which predates generics

    Dictionary<string, string> dict = new Dictionary<string, string>();
        // + Strong Type
        // - random order ?

    List<KeyValuePair<string, string>> listKVP = new List<KeyValuePair<string, string>>();
        // + Strong Type
        // + Keeps order as inserted
        // - more complex to instanciate and use

    Hashtable hash = new Hashtable();
        // Automatically sorted by hash code
        // Better for big collections
        // - not strong typed

    ListDictionary listDict = new ListDictionary();
        // + faster than Hashtable for small collections (smaller than 10)
        // - not strong typed

    HybridDictionary hybridDict = new HybridDictionary();
        // Better compromise if unsure of length of collection
        // - not strong typed

    OrderedDictionary orderDict = new OrderedDictionary();
        // + Keeps order as inserted
        // - not strong typed

    SortedDictionary<string, string> sortedDict = new SortedDictionary<string, string>();
        // + Strong Type
        // Automatically sorted by key
        // + faster lookup than the Dictionary [msdn]

    SortedList<string, string> sortedList = new SortedList<string, string>();
        // + Strong Type
        // Automatically sorted by key
        // Almost same as SortedDict, but can access by index []

    KeyValuePair<string, string>[] arrayKVP = new KeyValuePair<string, string>[123];
        // + Strong Type
        // + Keeps order as inserted
        // - Fixed size

bash_79
  • 173
  • 4