20

I was looking at some sample code and in it they used a ListDictionary object to store a small amount of data (around 5-10 objects or so, but this number could change over time). The only issue I have with using this class is that, unlike everything else I've been doing, it's not generic. This means, and correct me if I'm wrong here, that every time I get an object out of here or enumerate over it that there's casting going on. Is there enough overhead in the larger Dictionary<T> object to justify the overhead of a non-generic ListDictionary?

The code that will be using this object will be enumerated over on each page load which I'm guessing is why the ListDictionary class was used over one of the other alternatives. This is also why I would like the most performance out of this list of data.

Dan Atkinson
  • 11,391
  • 14
  • 81
  • 114
Brian Surowiec
  • 17,123
  • 8
  • 41
  • 64
  • Did you reach a conclusion on this and do any performance measurement? It always bothers me using a `Dictionary` when there'll only be a handful of items in the collection, but the convenience of it being there has always outweighed the bother/risk associated with choosing or writing something else. Not a big deal performance-wise ... unless it is. – Rory May 30 '16 at 10:22

5 Answers5

12

Unfortunately there is no generic equivalent of ListDictionary.

However it shouldn't be terribly difficult to implement one. ListDictionary essentially works by keeping a linked list of Key/Value pairs and iterating over them for lookup operations. You could build a ListDictionary<TKey,TValue> by wrapping a LinkedList<T> with some very simple LINQ expressions.

For example

public class LinkedDictionary<TKey,TValue> {
  private LinkedList<KeyValuePair<TKey,TValue>> _list = new LinkedList<KeyValuePair<TKey,TValue>>();
  private IEqualityComparer<TKey> _comp = EqualityComparer<TKey>.Default;

  public void Add(TKey key, TValue value) { 
    _list.Add(new KeyValuePair<TKey,TValue>(key,value)); 
  }
  public TValue Get(TKey key) {  
    return _list.Where(x => _comp.Equals(x.Key,key)).First().Value;
  }
  ...
}
Steve Dunn
  • 21,044
  • 11
  • 62
  • 87
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 6
    I would imagine using LINQ would negate almost all performance benefits of using a ListDictionary unless calculating Hash Codes was hideously expensive. – Chuu Mar 26 '12 at 21:26
  • @Chuu But ListDictionary already calls Equals on each key when accessing values so why should provided LINQ's Where have any negative influence on performance? – sluki Sep 01 '14 at 08:08
  • 2
    @sluki Object allocations and delegate invocations versus a single method containing a for loop. LINQ is for readability, not for framework code. – jnm2 Apr 17 '15 at 15:53
  • Agreed that you would likely lose any perf benefits by enumerating with Linq (and perf is probably a primary consideration if you're thinking of using a collection that's optimised for <=10 items). Here's a good post on Linq performance: https://mattwarren.org/2016/09/29/Optimising-LINQ/ – Steve Dunn Mar 17 '21 at 06:01
6

There is no generic equivalent of ListDictionary.

If your use of this small dictionary isn't dominated by Add and Remove, you might consider SortedList<TKey, TValue> which, despite its name, implements IDictionary<TKey, TValue>. Unlike ListDictionary which is backed by a singly-linked list, SortedList is backed by an array of sorted keys and an array values.

Carl Reinke
  • 345
  • 2
  • 12
4

If the data you are storing in the ListDictionary is always objects (classes), rather than value types, then it would probably be faster than Dictionary<T>. If you will be storing value types (structs, int, double, etc.), then the cost of boxing/unboxing will most likely balance things out, and I would recommend the Dictionary<T> instead.

Overall, however, I would point out that the performance difference between these two are likely to be the least of your performance problems overall. Small things like this are generally the last thing to worry about when it comes to performance optimization. Larger scale things, such as inter-process calls, database and web service interaction, etc. should be addressed first before ever being concerned about the minor performance difference between ListDictionary and Dictionary<T>.

jrista
  • 32,447
  • 15
  • 90
  • 130
  • I fully agree that there are bigger things to worry about in terms of performance. The reason for asking this though is it's something I'm looking over now, and adding in to the project now. So if I can use a better alternative to the ListDictionary class from the get go then I figure that's better than leaving it as-is. – Brian Surowiec Aug 05 '09 at 18:51
1

A simple check on MSDN-ListDictionary class will reveal

This is a simple implementation of IDictionary using a singly linked list. It is smaller and faster than a Hashtable if the number of elements is 10 or less. This should not be used if performance is important for large numbers of elements.

Stan R.
  • 15,757
  • 4
  • 50
  • 58
1

We can use,

    System.Collections.Generic.Dictionary<Object,Object> dictTemp = new System.Collections.Generic.Dictionary<Object,Object>();

For Example, Consider the following,

    using System.Collections.Specialized;

    private ListDictionary  g_Attributes = new ListDictionary();
    public ListDictionary Attributes
    {
        get { return this.g_Attributes; }
    }
    public string GetAttribute(string name)
    {
        if (HasAttribute(name))
            return (string) g_Attributes[name];
        else
            return null;
    }
    public bool HasAttribute(string name)
    {
        return this.Attributes.Contains(name);
    }


    using System.Collection.Generic;

    private Dictionary<string, object> g_Attributes = new Dictionary<string, object>();
    public Dictionary<string, object> Attributes
    {
        get { return this.g_Attributes; }
    }
    public string GetAttribute(string name)
    {
        if (HasAttribute(name))
        {
            return g_Attributes[name].ToString();
        }
        else
        {
            return null;
        }
    }
    public bool HasAttribute(string name)
    {
    return this.Attributes.ContainsKey(name);
    }

I think this will help you a little!

ggsmartboy
  • 454
  • 7
  • 14