API Design – Should Strings or Enums Be Used for Dictionary Keys?

apiapi-designcdata typesdictionary

I am working on an API in C#. I am trying to think about the simplest way to expose my API for consumers of it. In particular, I have a class in my exposed data model that has a dictionary property. I'm trying to decide if the dictionary property should use strings as keys or an enum that I define as keys.

My concern with using strings as keys is that then the burden lies in the documentation to provide every possible string key value and the consumers end up working with string literals which could result in typos or duplication.

My concern with enums is that if we ever need to change the list of possible dictionary keys, this could be a breaking change for the API.

I'm leaning toward the enum, but my colleagues feel that a string would be best. Does anyone out there have any thoughts or advice on this?

Best Answer

How is the API exposed? Through an ordinary .NET interface, or through REST or similar?

  • In the first case, enums are a good choice if you have a limited amount of accepted values. You can check valid values with Enum.IsDefined, you can have inline XML documentation explaining each value, and typo errors are checked by the compiler (and are caught even earlier with a capable IDE).

    Make sure everybody uses the values in a form MyEnum.SomeValue, and not in a form of underlying integers. If somebody uses integers, the risk is that when changing the order of the values within the enum or adding the values in the middle of it or removing values will change the match between some values and the underlying numbers.

    Also note the importance of Enum.IsDefined. The following code, and especially the last line, is perfectly valid, and will compile and run without errors. Guess what will be the console output?

    enum Color
    {
        Red = 1,
        Green = 2,
        Blue = 3,
    }
    
    void Demo(Color color)
    {
        Console.WriteLine(color.ToString());
    }
    
    Demo((Color)4);
    
  • In the second case, the values from enum will usually appear as numbers, and remembering what means 14 or 17 in a given context is not particularly exciting. So here, stick with meaningful string values.

    Make sure you use an explicit map instead of a simple ToString. Renaming a value within the enum is a simple refactoring task and shouldn't break the code. If the string value matches the actual value name within the enum, the code will break in a subtle way which wouldn't be easy to debug.

    See also: Is this a Best Practice with Enum in C# and the comments by MK87.