For illustration, I’ve an enum class Genre with different enum fields and ToString() method will produce different results under different scenarios.
For examples,
Case 1:
public enum Genre {
A1 = 1, // .ToString() produces "A2"
A2 = A1, // .ToString() produces "A2"
B1 = 2, // .ToString() produces "B1" (Why not "B2"?)
B2 = B1 // .ToString() produces "B1" (Why not "B2"?)
}
Case 2:
public enum Genre {
A1 = 1, // .ToString() produces "A2"
A2 = A1, // .ToString() produces "A2"
B1 = 2 // .ToString() produces "B1"
}
Case 3:
public enum Genre {
A1 = 1, // .ToString() produces "A1" (Why not "A2"?)
A2 = A1 // .ToString() produces "A1" (Why not "A2"?)
}
Below are the experiment screenshots that I had done via Rider’s Immediate Window. Another workaround is to use nameof() but major places in our code base are using ToString() and we do not want to change them.
>Solution :
The docs state:
If multiple enumeration members have the same underlying value and you
attempt to retrieve the string representation of an enumeration
member’s name based on its underlying value, your code should not
make any assumptions about which name the method will return.
If you look at the source, you see the reason is that Enum.ToString uses GetEnumName which uses GetEnumData which uses reflection to get the names of all enum values, then uses Array.BinarySearch to find the first matching. So it’s not predictable what name you get and you should not rely on it.
If you must rely on the name you should consider to use a Dictionary<Genre, string> or a real class, for example FilmGenre which has string Name and maybe Genre Genre properties.