How to Tryparse for Enum Value

How to TryParse for Enum value?

As others have said, you have to implement your own TryParse. Simon Mourier is providing a full implementation which takes care of everything.

If you are using bitfield enums (i.e. flags), you also have to handle a string like "MyEnum.Val1|MyEnum.Val2" which is a combination of two enum values. If you just call Enum.IsDefined with this string, it will return false, even though Enum.Parse handles it correctly.

Update

As mentioned by Lisa and Christian in the comments, Enum.TryParse is now available for C# in .NET4 and up.

MSDN Docs

C# Enum.TryParse parses invalid number strings

Internally, enums are stored as integers so that's likely why TryParse is returning true for integers being passed in.

Regarding why any integer is working, it's by design. From MSDN (emphasis mine):

When this method returns, result contains an object of type TEnum
whose value is represented by value if the parse operation succeeds.
If the parse operation fails, result contains the default value of the
underlying type of TEnum. Note that this value need not be a member of
the TEnum enumeration
. This parameter is passed uninitialized.

Enum.TryParse returns true for any numeric values

This behavior is by design.

The documentation says:

. If value is the string representation of an integer that does not represent an underlying value of the TEnum 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 TEnum.

Call Enum.IsDefined to veryify that the value you parsed actually exists in this particular enum.

If you're dealing with [Flags] enums (bitmasks), it'll get more complicated.

How to use generic Tryparse with Enum?

The TryParse method has the following signature:

TryParse<TEnum>(string value, bool ignoreCase, out TEnum result)
where TEnum : struct

It has a generic type parameter TEnum that must be a struct and that is used to determine the type of enumeration being parsed. When you don't provide it explicitly (as you did), it will take the type of whatever you provide as the result argument, which in your case is of type Enum (and not the type of the enumeration itself).

Note that Enum is a class (despite it inheriting from ValueType) and therefore it does not satisfy the requirement that TEnum is a struct.

You can solve this by removing the Type parameter and giving the method a generic type parameter with the same constraints (i.e. struct) as the generic type parameter on the TryParse function.

So try this, where I've named the generic type parameter TEnum:

private static TEnum GetEnumStringEnumType<TEnum>()
where TEnum : struct
{
string userInputString = string.Empty;
TEnum resultInputType = default(TEnum);
bool enumParseResult = false;

while (!enumParseResult)
{
userInputString = System.Console.ReadLine();
enumParseResult = Enum.TryParse(userInputString, true, out resultInputType);
}
return resultInputType;
}

To call the method, use:

GetEnumStringEnumType<MyEnum>();

Very basic use of Enum.TryParse doesn't work

As you can see from the documentation, Enum.TryParse<TEnum> is a generic method that returns a boolean property. You are using it incorrectly. It uses an out parameter to store the result:

string value = "Dog";
PetType pet;
if (Enum.TryParse<PetType>(value, out pet))
{
if (pet == PetType.Dog)
{
...
}
}
else
{
// Show an error message to the user telling him that the value string
// couldn't be parsed back to the PetType enum
}

F# Equivalent of Enum.TryParse

This is a rather unhelpful (if technically correct) message that the compiler gives you if you try to parse a discriminated union value using Enum.TryParse.

More precisely, if you look at that function, you'll see that it's parameterized with a type that's constrained to be a value type with a default constructor. DU's meet neither of this criteria - this is what the compiler complains about.

When defining an enum in F#, unlike C#, you need to explicitly give each label a value:

type MyEnum = 
| Default = 0
| Custom = 1
| Fancy = 2

Skipping the values would make the compiler interpret the type as a discriminated union, which is a very different beast.

Enum.TryParse and Enum.IsDefined returns false for char Enums

Enum.TryParse is for parsing the Names of enum elements or a string representation of the underlying numeric value (e.g. "123" for 123). If you already have the actual value as a char, you can use a cast:

char _status = 'C'
var status = (MyStatus)_status;

If you're worried that it might not be one of the valid values, you can combine this with Enum.IsDefined():

if (Enum.IsDefined(typeof(MyStatus), (int)_status))
{
var status = (MyStatus)_status;
Console.WriteLine(status);
}
else
{
Console.WriteLine("Not a valid value.");
}

Enum.TryParse strange behaviour

Enum.TryParse Method (String, TEnum)

If value is a name that does not correspond to a named constant of
TEnum, the method returns false. If value is the string representation
of an integer that does not represent an underlying value of the TEnum
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 TEnum.

"Returns an enumeration member whose underlying value is value converted to an integral type"

If the value is not present you get back the integer. I don't consider getting back 5 to be an "enumeration member" but that is how it works. If you parse 2 you get FirstOption.

if (Enum.IsDefined(typeof(TestEnum), 5.ToString()))
{
result = Enum.TryParse<TestEnum>(5.ToString(), out enumValue);
Debug.WriteLine(result);
if (result)
{
Debug.WriteLine(enumValue.ToString());
}
}

TryParse of Enum is working, but I think it shouldn't

From the MSDN page for Enum.TryParse<TEnum>(string value, ...):

If value is the string representation of an integer that does not represent an underlying value of the TEnum 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 TEnum.



Related Topics



Leave a reply



Submit