For your own enums, use the numeric values, for one simple reason: it allows for every part of enum
functionality, out of the box, with no hassle. The only caveat is that in the enum
definition, every member must be explicitly given a numeric value, which can never change (or, at least, not after you've made the first release). I always add a prominent comment to enums that get persisted to the database, so people don't go changing the constants.
Here are some reasons why numeric values are better than string identifiers:
- It is the simplest way to represent the value
- Database searching/sorting is faster
- Lower database storage cost (which could be a serious issue for some applications)
- You can add
[Flags]
to your enum
and not break your code and/or existing data
- For
[Flags]
stored in a string field:
- Poorly normalized data
- Could generate false-positive anomalies when doing matching (i.e., if you have members "Sales" and "RetailSales", merely doing a substring search for "Sales" will match on either type). This has to be constrained either by using a regex on word boundaries (finicky using databases, and slow), or constraining in the enum itself, which is nonstandard, error-prone, and very difficult to debug.
- For string fields (either
[Flags]
or not), if the database is obfuscated, this field has to be handled, which greatly affects the ability and efficiency when doing searching/sorting code, as mentioned in the previous point
- You can rename any of the members without breaking the database code and/or existing client data.
- Less over-the-wire data transfer space/time needed
There are only two situations where using the member names in the database may be an advantage:
- If you're doing a lot of data editing manually... but who does that? And if you are, there's a good chance you're not going to be using an
enum
anyway.
- Third-party enums where they may not be so diligent as to maintain the numeric value constants. But I have to say, anyone releasing a decently-written API is overwhelmingly likely to be smart enough to keep the
enum
values constant. (The identifiers have to stay the same since changing them would break existing code.)
On lookup tables, which I strongly discourage because they are a one-way bullet train to a maintenance nightmare:
- Adding
[Flags]
functionality requires the use of a junction table, which means more complicated queries (existing ones need to be rewritten), and added complexity. What about existing client data?
- If the identifier is stored in the data table, what's the point of having a lookup table in the first place?
- If the numeric value is stored in the data table, you gain nothing since you still have to look up the identifier from the lookup table. To make it easier, you could create a view... for every table that has an
enum
value in it. And then let's not even think about [Flags]
enums.
- Introducing any kind of synchronization between database and code is just asking for trouble. What about existing client data?