I am an iOS developer and I regret that in Objective-C there is no the amazing method toString for enum like in C#
So I am very curious to know how the toString method works for enum in C#.
Maybe with your answers I will understand why Objective-C has not this method implemented.
Thanks
toString() method returns the name of this enum constant, as contained in the declaration.
To localize the enumeration names and values, add messages with the following keys to the message pack located in the Java package of the enumeration class: Enumeration name key – simple class name (without package); Value key – simple class name, then the value name separated by period.
The toString() method of Enum class returns the name of this enum constant, as the declaration contains. The toString() method can be overridden, although it's not essential.
By default, Enum. toString() returns the same value as Enum.name().
The C# compiler actually turns enumerations into regular class
types, and makes them behave like an enumeration by a combination of syntax sugar and some help from methods in the .NET framework (particularly the Type
and Enum
classes).
What actually happens when you declare an enum
type is that the compiler creates a hidden, specially-named class which conceptually looks like this:
public sealed class EnumName : Enum
{
public static readonly int FirstValue = 0;
public static readonly int SecondValue = 1;
// etc.
}
The Enum
base class is a special base class that you cannot use directly. It provides the ToString()
method. This sets off a series of function calls internal to the .NET framework. The code ends up in Type.GetEnumName()
and finally a private Type.GetEnumData()
method which uses reflection to examine the EnumName
class, look at its fields (enumeration values) and get and return their names.
The call graph (in chronological order) looks like this:
Enum.ToString()
Enum.InternalFormat(RuntimeType, object)
Enum.GetName(RuntimeType, object)
Type.GetEnumName(object)
Type.GetEnumRawConstantValues()
Type.GetEnumData(out string[], out Array)
Type.GetEnumNames()
Type.GetEnumData(out string[], out Array)
GetEnumData()
calls Type.GetFields()
and iterates over them, copying the name and integral value (enum value) of each field into the output array.
Internally ToString
will call a method called Enum.InternalFormat
, which in turn just calls Enum.GetName
, here's the decompiled code (.NET v4.0)
[__DynamicallyInvokable]
public override string ToString()
{
return Enum.InternalFormat((RuntimeType) this.GetType(), this.GetValue());
}
private static string InternalFormat(RuntimeType eT, object value)
{
if (!eT.IsDefined(typeof (FlagsAttribute), false))
return Enum.GetName((Type) eT, value) ?? value.ToString();
else
return Enum.InternalFlagsFormat(eT, value);
}
For enums marked with the Flags
attribute, it calls another method called InternalFlagsFormat
which builds up a CSV of all the enum names
private static string InternalFlagsFormat(RuntimeType eT, object value)
{
ulong num1 = Enum.ToUInt64(value);
ulong[] values;
string[] names;
Enum.GetCachedValuesAndNames(eT, out values, out names, true, true);
int index = values.Length - 1;
StringBuilder stringBuilder = new StringBuilder();
bool flag = true;
ulong num2 = num1;
for (; index >= 0 && (index != 0 || (long) values[index] != 0L); --index)
{
if (((long) num1 & (long) values[index]) == (long) values[index])
{
num1 -= values[index];
if (!flag)
stringBuilder.Insert(0, ", ");
stringBuilder.Insert(0, names[index]);
flag = false;
}
}
if ((long) num1 != 0L)
return value.ToString();
if ((long) num2 != 0L)
return ((object) stringBuilder).ToString();
if (values.Length > 0 && (long) values[0] == 0L)
return names[0];
else
return "0";
}
For the latest implementation, see the Microsoft source reference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With