1

Recently I've discovered that any string that contains only numeric characters can be converted to enum in C#. For example, imagine there is an enum defined as follows:

public enum TestEnum
{
    One = 1,
    Two = 2,
    Three = 3
};

I can perform a conversion of some random numeric string to TestEnum.

TestEnum testEnum = (TestEnum)Enum.Parse(typeof(TestEnum), "4");
Console.WriteLine(testEnum);

The value '4' of course does not get mapped to one of defined TestEnum values and the output would be just 4, however there would be no error, so this conversion is legal.

On the other hand, if I try to check whether this value defined in TestEnum:

Console.WriteLine(Enum.IsDefined(typeof(TestEnum), "4"));

I would receive False in the output.

This seems a little strange to me, taking into account that the following conversion of non-numeric string, e.g.

(TestEnum)Enum.Parse(typeof(TestEnum), "Test")

will throw System.ArgumentException.

I am confused with such behavior. Was it intentionally designed this way or is this just a coincidence?

1
  • 2
    An enum is a numeric type under the hood (an int, unless explicitely declared otherwise). As such, it can hold any value within the value range of the particula numeric type. Considering this, the behavior you describe is not so strange, even though it can be a little confusing to have an enum variable containing a value that is not one of the defined named values. (This behavior is explained/documented here: learn.microsoft.com/en-us/dotnet/csharp/language-reference/…) Commented Mar 23, 2019 at 17:44

1 Answer 1

3

Was it intentionally designed this way or is this just a coincidence?

I'm not sure I understand your question. The documentation seems completely clear to me:

Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object.

(Emphasis mine)

It also says:

If value is the string representation of an integer that does not represent an underlying value of the enumType enumeration, the method returns an enumeration member whose underlying value is value converted to an integral type. If this behavior is undesirable, call the IsDefined method to ensure that a particular string representation of an integer is actually a member of enumType

Clearly this is intentional behavior, and not just coincidental.

Note that you can always cast any value of the enum's underlying type (int in this case), to the enum type itself. The enum type feature does not enforce values of the enum to correspond to named value. So the parsing behavior is entirely consistent with the compile-time behavior of enum types.

I suppose one might debate whether the enum type should allow unnamed values to be used. But, given that one of the features of enum types is to allow for flag-based enums, whether or not they have the [Flags] attribute, and given that it would be inconvenient (to say the least) to have to name every single combination of every single flag one defines in an enum type, it seems reasonable that they would go ahead and allow unnamed values for all types of enum types.

Sign up to request clarification or add additional context in comments.

2 Comments

That documentation seems completely WRONG to me, because it says "numeric value of one or more enumerated constants" and there is no such restriction (as the OP found)
@Ben: you may quibble with the wording of the summary, if you like. However, the documentation also clearly states "If value is the string representation of an integer that does not represent an underlying value of the enumType enumeration, the method returns an enumeration member whose underlying value is value converted to an integral type. If this behavior is undesirable, call the IsDefined method to ensure that a particular string representation of an integer is actually a member of enumType"

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.