Enum.ToString 可以支持像 "X2" 这样的精度说明符吗?

Can Enum.ToString support precision specifiers like "X2"?

Enum.ToString(string) 不支持直接使用 X2D5 等精度说明符来对数值应用填充。 Formattings like ToString("X") or ToString("D") are implemented and well documented。当然,我可以明确地将它转换为 int 之前,因此利用为 ints 实现的格式说明符将其转换为填充字符串。

我想知道是否有一些直接支持枚举的这种功能而无需转换它们。乍一看,这似乎很奇怪,因为它不是直接实现的,因为它是为 int 或其他数字类型完成的。但也许我遗漏了一些更重要的东西,它可以明确地解释枚举不是那样做的?

public enum Number
{
    Ten = 10
}

Console.WriteLine(Number.Ten);                      //OK: Ten
Console.WriteLine(Number.Ten.ToString());           //OK: Ten
Console.WriteLine(Number.Ten.ToString("D"));        //OK: 10
Console.WriteLine(Number.Ten.ToString("D5"));       //Expected 00010 - Failed: System.FormatException, can only be "G","g","X","x","F","f","D" or 
Console.WriteLine(Number.Ten.ToString("X"));        //OK: 0000000A
Console.WriteLine(Number.Ten.ToString("X2"));       //Expected 0A - Failed: System.FormatException, can only be "G","g","X","x","F","f","D" or "d"
Console.WriteLine(10.ToString("X2"));               //OK: 0A
Console.WriteLine(10.ToString("D5"));               //OK: 00010
Console.WriteLine(((int)Number.Ten).ToString("X2"));//OK: 0A 

来自 的简短摘要: 它不是明确存在的,因为它已经根据基础类型的大小隐式完成。因此,如果您喜欢 X2 而不是 X8,只需使用字节作为基础类型,ToString("X") 的行为将类似于 ToString("X2")

Enum.ToString() 的实现表明它的设计使得只能使用某些格式说明符:

    public String ToString(String format) {
        if (format == null || format.Length == 0)
            format = "G";

        if (String.Compare(format, "G", StringComparison.OrdinalIgnoreCase) == 0)
            return ToString();

        if (String.Compare(format, "D", StringComparison.OrdinalIgnoreCase) == 0)
            return GetValue().ToString();

        if (String.Compare(format, "X", StringComparison.OrdinalIgnoreCase) == 0)
            return InternalFormattedHexString(GetValue());

        if (String.Compare(format, "F", StringComparison.OrdinalIgnoreCase) == 0)
            return InternalFlagsFormat((RuntimeType)GetType(), GetValue());

        throw new FormatException(Environment.GetResourceString("Format_InvalidEnumFormatSpecification"));
    }

我认为它涵盖了最常见的场景:能够显示其数字、十六进制或字符串表示形式。显式转换的解决方法似乎足够便宜,不需要将其烘焙到框架中。

如果您想在不知道特定类型是什么的情况下使用基础类型的 ToString()(无需转换!),您可以这样做:

var formattedValue = string.Format("{0:X2}", 
    Convert.ChangeType(Number.Ten, Number.Ten.GetTypeCode()));

这将输出“0A”。这可以很容易地包含在扩展方法中。

可能是因为枚举可以是字节、sbyte、short、ushort、int、uint、long 或 ulong。

如果您查看 .net 源代码,您将看到 ToString("X"):

的实现
switch (Convert.GetTypeCode(value))
  {
    case TypeCode.Boolean:
      return Convert.ToByte((bool) value).ToString("X2", (IFormatProvider) null);
    case TypeCode.Char:
      return ((ushort) (char) value).ToString("X4", (IFormatProvider) null);
    case TypeCode.SByte:
      return ((byte) (sbyte) value).ToString("X2", (IFormatProvider) null);
    case TypeCode.Byte:
      return ((byte) value).ToString("X2", (IFormatProvider) null);
    case TypeCode.Int16:
      return ((ushort) (short) value).ToString("X4", (IFormatProvider) null);
    case TypeCode.UInt16:
      return ((ushort) value).ToString("X4", (IFormatProvider) null);
    case TypeCode.Int32:
      return ((uint) (int) value).ToString("X8", (IFormatProvider) null);
    case TypeCode.UInt32:
      return ((uint) value).ToString("X8", (IFormatProvider) null);
    case TypeCode.Int64:
      return ((ulong) (long) value).ToString("X16", (IFormatProvider) null);
    case TypeCode.UInt64:
      return ((ulong) value).ToString("X16", (IFormatProvider) null);
    default:
      throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType"));
  }

如果您将代码更改为此,它将使用 ToString("X2"):

public enum Number : byte
{
    Ten = 10
}