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?
2
How is the API exposed? Through an ordinary .NET interface, or through REST or similar?
-
In the first case,
enum
s are a good choice if you have a limited amount of accepted values. You can check valid values withEnum.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 theenum
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 means14
or17
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 theenum
is a simple refactoring task and shouldn’t break the code. If the string value matches the actual value name within theenum
, 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.
1
If the object represented by your Dictionary has a finite, well-defined set of values that can be identified ahead of time (which seems like it must be true, otherwise you wouldn’t be able to use an enum
for the key), then why are you using a Dictionary at all? Create a data class or struct that has one field for each possible value. This has several benefits:
- Better IDE integration: consumers will see see automatic completion of the field names in their IDE without having to specifically identify which
enum
they want to pull the data out of. Documentation will be easier to find than it would be for anenum
. - Better type safety: unless all of your data items have exactly the same type, you can specify exact types for the fields and make sure that the data is correctly used at compile time
- Better efficiency: an object has virtually-zero-time lookup and modification cost. It uses the minimum amount of memory that could be possibly stored for the data that you need to keep. It interacts with the GC in much cleaner fashion.
Honestly, I fail to see the advantage of using a Dictionary here at all.
4