For this example, let's say we have a list of Roles that our
application uses, and these roles include Authors, Editors, and Sales
Representatives. To model this with an enum, we can use something like this:

Now anywhere in our code that we need to use a Role, instead
of using a string or an integer ID for the role, we can simply specify
Role.Author or Role.Editor, etc. The resulting code will be much more
readable.
However, enums are not without their limitations. A very
common use case for enumerations is the creation of user interface elements
that allow the end user to choose from a list of options. Since enums' element
names must follow C# naming conventions, they cannot, for instance, have spaces
in them. Thus if you were to have the following bit of code for displaying the
above enum listing, and you expected to have "Sales Representative"
listed instead of the concatenated version use by the enum, your code (and the
test shown) would fail.


Enumerations, while type-safe, are not as safe as many
believe when it comes to using them as parameters. For instance, if
enumerations only supported the named values specified, the following method
would correctly model the behavior that Editors and Sales Representatives
should be able to do something, but Authors should not.

However, it allows for the possibility of an invalid input
to be granted access. Consider this test and result:


There are no built-in range checks performed on
enumerations, for performance reasons (see
more here). If you're going to use them, it's your responsibility to
verify the values you're receiving are valid. The simplest way to do so is to
use the Enum.IsDefined() method, like so:
