enum.toString()如何在引擎盖下工作?

时间:2014-03-25 16:00:46

标签: c# enums tostring

我是一名iOS开发人员,我很遗憾在Objective-C中没有像C#中那样令人惊奇的方法来实现枚举#

所以我很想知道toString方法如何适用于C#中的枚举。

也许有了你的答案,我将理解为什么Objective-C没有实现这个方法。

由于

4 个答案:

答案 0 :(得分:8)

C#编译器实际上将枚举转换为常规class类型,并使它们的行为类似于syntax sugar的组合以及.NET框架中某些方法的帮助(特别是{{3 }和Type类)。

当您声明enum类型时,实际发生的是编译器创建一个隐藏的,特别命名的类,其概念如下所示:

public sealed class EnumName : Enum
{
    public static readonly int FirstValue = 0;
    public static readonly int SecondValue = 1;
    // etc.
}

Enum基类是一个不能直接使用的特殊基类。它提供ToString()方法。这引发了.NET框架内部的一系列函数调用。代码最终在Enum中,最后是一个私有Type.GetEnumData()方法,它使用反射来检查EnumName类,查看其字段(枚举值)并获取并返回其名称。

调用图(按时间顺序)如下所示:

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()调用Type.GetEnumName()并迭代它们,将每个字段的名称和整数值(枚举值)复制到输出数组中。

答案 1 :(得分:2)

内部ToString将调用一个名为Enum.InternalFormat的方法,该方法只调用Enum.GetName,这里是反编译代码(.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);
}

对于标有Flags属性的枚举,它会调用另一个名为InternalFlagsFormat的方法,该方法会构建所有枚举名称的CSV

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";
} 

有关最新实施,请参阅Microsoft source reference

答案 2 :(得分:0)

ToString只返回特定枚举值的名称等效字符串(注意,这可能与它的值不同)。

public enum SomeEnum {
    Text1 = 1,
    Text2 = 2,
    Text3 = 3,
}

var some = SomeEnum.Text1

some.ToString()返回"Text1"

如果是标记的枚举(在声明中使用FlagsAttribute),它将返回一个等于所有选定枚举值的字符串

var some = SomeEnum.Text1 & SomeEnum.Text2

"Text1 | Text2"

答案 3 :(得分:0)

如果我们有一个枚举类型的实例,我们可以通过调用从System.Enum继承的ToString方法将该值映射到几个字符串表示之一

以下是示例代码

class Program
{
    enum Days
    {
        Sun,
        Mon,
        Tue,
        Wed,
        Thu,
        Fri,
        Sat
    };

    static void Main(string[] args)
    {

        Days obj = Days.Mon;

        Console.WriteLine(obj.ToString("G"));  // output - Mon (Normal)
        Console.WriteLine(obj.ToString("D"));  // output - 1 (Decimal)
        Console.WriteLine(obj.ToString("X"));  // output - 00000001 (Hexadecimal)    
    }
}