While trying to track down a bug in an internal conversion library, I stumbled upon unexpected behavior with TypeConverter.ConvertFromString
when trying to convert to an enum type.
The following method an enum type can be used to demonstrate the issue:
MyEnum? Convert(string s)
{
var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(MyEnum)); // Creates an EnumConverter
try
{
var converted = converter.ConvertFromString(s);
return converted != null ? (MyEnum)converted : null;
}
catch (Exception e)
{
Console.WriteLine($"({e.GetType().Name}: Failed to convert {s} to {nameof(MyEnum)} - {e.Message})");
return null;
}
}
enum MyEnum { First , Second }
Calling this method with valid enum values (even for int values that are outside the definition of MyEnum
) yields the expected result:
Console.WriteLine(Convert("0")); // First
Console.WriteLine(Convert("Second")); // Second
Console.WriteLine(Convert("2")); // 2
Calling the method with invalid enum values also yields the expected result:
Console.WriteLine(Convert("x")); // (FormatException: Failed to convert x to MyEnum - x is not a valid value for MyEnum.)
Console.WriteLine(Convert("1.2")); // (FormatException: Failed to convert 1.2 to MyEnum - 1.2 is not a valid value for MyEnum.)
However, for certain values that i would expect to also be invalid - a string with int values separated by ,
- the conversion succeeds in a way I cannot explain - neither why it succeeds nor the conversion it does:
Console.WriteLine(Convert("1,2")); // 3
Console.WriteLine(Convert("2,3")); // 3
Console.WriteLine(Convert("3,4")); // 7
Console.WriteLine(Convert("4,5")); // 5
Handling this would be easy enough - one could for instance test if the input contains ,
, and if so return null
straight away - so that is not the issue of this question.
Question: I would however very much like to know why these conversions with "1,2"
etc. doesn't throw an exception. And I am also very curious to know what the logic behind the result in these cases is.
The above code is tested with both .NET 6 and .NET 7, but I can also confirm the same behavior with .NET Framework 4.8.
The comma-separated value notation is a way to format Flags
enums, so the resulting value is the bitwise or
of the specified values.
That the converter performs this logic whether or not the type is annotated with Flags
, and whether or not the numbers represent tags, could be considered a bug, but then, there's plenty of weirdness (legacy or otherwise) in the generic converter classes.
Note that Enum.Parse
does not exhibit this behavior.