Using a List, Lookup or Dictionary for a large list of data

Mark Kram picture Mark Kram · Jul 22, 2012 · Viewed 20.1k times · Source

I have a static class in my Class Library called Lookup, I am using this class to look up different values (in this case Locations).

These values can number into the hundreds. Since 95% of my customers install my app on a machine without Internet access I have to assume that my applications will not have internet access nor access to a database.

So I want to know if this is an efficient way of handling this and if I am properly disposing the object when the method is done:

CODE :

using System;
using System.Collections.Generic;

namespace FunctionLibrary
{
    public static class Lookups
    {
        private static List<Vers> Versions;

        public static string GetVersion(string s)
        {
            string retValue = string.Empty;
            Versions = new List<Vers>();

            try
            {
                if (s.Trim().Length > 0)
                {

                    GetVersions();
                    retValue = Versions.Find(ver => ver.VersionNumber == s).VersionLiteral;

                    if (string.IsNullOrEmpty(retValue))
                    {
                        retValue = string.Format("{0} is an Unknown Version Number", s);
                    }
                }
                else
                {
                    retValue = "No version number supplied";
                }
            }
            catch
            {
                retValue = string.Format("{0} is an Unknown Version Number", s);
            }
            finally
            {
                Versions.Clear();
                Versions = null;
            }
            return retValue;
        }

        private static void GetVersions()
        {
            Versions.Add(new Vers() { VersionNumber = "0000", VersionLiteral = "Location 1" });
            Versions.Add(new Vers() { VersionNumber = "0001", VersionLiteral = "Location 2" });
            Versions.Add(new Vers() { VersionNumber = "0002", VersionLiteral = "Location 3"});
            Versions.Add(new Vers() { VersionNumber = "0003", VersionLiteral = "Location 4"});
            Versions.Add(new Vers() { VersionNumber = "0004", VersionLiteral = "Location 5"});
            Versions.Add(new Vers() { VersionNumber = "0005", VersionLiteral = "Location 6"});
            Versions.Add(new Vers() { VersionNumber = "0006", VersionLiteral = "Location 7"});
            Versions.Add(new Vers() { VersionNumber = "0007", VersionLiteral = "Location 8"});
        }
    }

    public class Vers
    {

        public string VersionLiteral { get; set; }
        public string VersionNumber { get; set; }
   }
}

I am also wondering if I should use a Dictionary or a Lookup instead of the list. I just don't want multiple calls to this method to cause memory issues.

Answer

Adam picture Adam · Jul 22, 2012

For a more thorough assessment, you might want to consider codereview.SE.


Some general notes on List<T> vs Dictionary<TKey, TValue> vs Lookup<TKey, TElement>

As other answers have shown, using a List is terrible in your scenario, mainly because looking up elements will have bad performance.

Choosing between Dictionary and Lookup isn't hard (from MSDN, emphasis mine):

A Lookup<TKey, TElement> resembles a Dictionary<TKey, TValue>. The difference is
that a Dictionary<TKey, TValue> maps keys to single values, whereas a Lookup<TKey, TElement> maps keys to collections of values.

You can create an instance of a Lookup<TKey, TElement> by calling ToLookup on an object that implements IEnumerable<T>.

Since you will only need to map keys to single values, a Dictionary is the right choice.


The previously accepted answer is a step in the right direction but still gets several key things wrong (edit: these problems have since been resolved).

Strings are immutable: s.Trim() will not change s — it will return a new string meaning you need to s = s.Trim() if you are using to s afterwards, which you are.

A static class can't have an instance constructor: public Lookups() should be static Lookups() (static constructors are not allowed to have access modifiers — of course).

Don't return an empty string / an error message as a string!

That's going to end up as a wonderful debugging headache. You should be using Exceptions instead of passing error strings around — and you should provide a VersionExists method to check if your dictionary contains a certain version!

Modified, safer example

This will throw a FormatException if the parameter is empty, null or whitespace. In the event that the version doesn't exist, the Dictionary will throw a KeyNotFoundException — a bit more helpful for debugging than string.Empty, don't you think?

public static class Lookups
{
    private static Dictionary<string, Vers> Versions;

    static Lookups()
    {
        Versions = new Dictionary<string, Vers>
        {
            {"0000", new Vers {VersionNumber = "0000", VersionLiteral = "Location 1"}},
            {"0001", new Vers {VersionNumber = "0001", VersionLiteral = "Location 2"}},
            {"0002", new Vers {VersionNumber = "0002", VersionLiteral = "Location 3"}},
            {"0003", new Vers {VersionNumber = "0003", VersionLiteral = "Location 4"}},
            {"0004", new Vers {VersionNumber = "0004", VersionLiteral = "Location 5"}},
            {"0005", new Vers {VersionNumber = "0005", VersionLiteral = "Location 6"}},
            {"0006", new Vers {VersionNumber = "0006", VersionLiteral = "Location 7"}},
            {"0007", new Vers {VersionNumber = "0007", VersionLiteral = "Location 8"}}
        };
    }

    public static bool VersionExists(string versionNumber)
    {
        return Versions.ContainsKey(versionNumber);
    }

    public static string GetVersion(string s)
    {
        if (string.IsNullOrWhiteSpace(s)) 
            throw new FormatException("Empty version number!");
        return Versions[s.Trim()].VersionLiteral;
    }
}