c# - 在具有多个对应名称的枚举值上调用 ToString() 时,什么决定选择哪个名称?

标签 c# .net enums clr tostring

在具有多个对应名称的 enum 值上调用 ToString() 时,什么决定选择哪个名称?

问题的详细解释如下。

我已经确定这不是由以下任何一个唯一确定的:字母顺序;申报单;也不,名称长度。

例如,假设我想要一个枚举,其中数值直接对应于实际用途(例如颜色的 rgb 值)。

public enum RgbColor 
{
    Black   = 0x000000,
    Red     = 0xff0000,
    Green   = 0x00ff00,
    Blue    = 0x0000ff,
    White   = 0xffffff
}

现在,使用此枚举,调用 default(RgbColor) 将返回黑色的 rgb 值。假设我不希望默认值为黑色,因为我希望 UI 设计人员在没有关于使用什么颜色的具体说明时能够使用对“默认”的调用。目前,UI 设计师使用的默认值实际上是“蓝色”,但这可能会改变。因此,我在枚举上添加了一个额外的 TextDefault 定义,现在它看起来像:

public enum RgbColorWithTextDefaultFirst
{
    TextDefault = 0x0000ff,
    Black   = 0x000000,
    Red     = 0xff0000,
    Green   = 0x00ff00,
    Blue    = 0x0000ff,
    White   = 0xffffff
}

现在,我已经对此进行了测试,我发现调用 RgbColorWithTextDefaultFirst.TextDefault.ToString()RgbColorWithTextDefaultFirst.Blue.ToString() 都会产生“蓝色”。所以,我认为最后声明的名称将覆盖之前声明的名称。为了验证我的假设,我写道:

public enum RgbColorWithTextDefaultLast
{
    Black   = 0x000000,
    Red     = 0xff0000,
    Green   = 0x00ff00,
    Blue    = 0x0000ff,
    White   = 0xffffff,
    TextDefault = 0x0000ff 
}

然而,令我惊讶的是,RgbColorWithTextDefaultLast.Blue.ToString()RgbColorWithTextDefaultLast.TextDefault.ToString()。我的下一个猜测是它按字母顺序对名称进行排序并返回第一个。为了测试这一点,我尝试:

public enum RgbColorWithATextDefaultFirst
{
    ATextDefault = 0x0000ff,
    Black   = 0x000000,
    Red     = 0xff0000,
    Green   = 0x00ff00,
    Blue    = 0x0000ff,
    White   = 0xffffff
}

public enum RgbColorWithATextDefaultLast
{
    Black   = 0x000000,
    Red     = 0xff0000,
    Green   = 0x00ff00,
    Blue    = 0x0000ff,
    White   = 0xffffff,
    ATextDefault = 0x0000ff
}

现在,对于所有四个 RgbColorWithATextDefaultFirst.ATextDefault.ToString()RgbColorWithATextDefaultFirst.Blue.ToString()RgbColorWithATextDefaultLast.ATextDefault.ToString()RgbColorWithATextDefaultLast.Blue.ToString(),我以“Blue”结尾。我意识到还有另一个区别因素,即字符串的长度。我现在的猜测是,所选名称由名称字符串的长度决定。所以,我的测试是使用这些声明:

public enum RgbColorWithALast
{
    Black   = 0x000000,
    Red     = 0xff0000,
    Green   = 0x00ff00,
    Blue    = 0x0000ff,
    White   = 0xffffff,
    A = 0x0000ff
}

public enum RgbColorWithAFirst
{
    A = 0x0000ff,
    Black   = 0x000000,
    Red     = 0xff0000,
    Green   = 0x00ff00,
    Blue    = 0x0000ff,
    White   = 0xffffff
}

现在,猜猜我得到的所有值是什么:RgbColorWithAFirst.A.ToString(); RgbColorWithAFirst.Blue.ToString(); RgbColorWithALast.A.ToString()RgbColorWithALast.Blue.ToString()。没错,就是“蓝”。

在这一点上,我已经放弃了试图通过猜测来弄清楚是什么决定了这一点。我打开了 Reflector,我打算看看并尝试弄清楚这个问题,但我想我会在这里问一个问题,看看这里是否有人已经知道答案,也就是:什么决定了在具有多个对应名称的 enum 值上调用 ToString() 时选择哪个名称?

最佳答案

我在这里可能走得太远了,但我认为它是由排序值的二进制搜索决定的,因此可能取决于值总数的奇偶校验。您可以通过在两者中定义另一个值来用最后一个示例(RgbColorWithAFirstRgbColorWithALast)来说明这一点 - 然后您从所有 中获得 A >ToString 调用。

我通过反编译 mscorlib (4.0) 到达这里,并注意到最终我们在声明值的排序数组上调用了 Array.BinarySearch。自然地,二分搜索一旦找到匹配项就会停止,因此要让它在两个相同的值之间切换,最简单的方法是通过添加一个额外的值来更改搜索树。

当然,这是一个实现细节,不应依赖。在我看来,在您的情况下,最好通过在您希望明确显示值的枚举值上使用 DescriptionAttribute 以及辅助方法,例如:

public static class EnumExtensions
{
    public static string Description(this Enum value)
    {
        var field = value.GetType().GetField(value.ToString());
        var attribute = Attribute.GetCustomAttribute(
                            field, 
                            typeof (DescriptionAttribute)) 
                        as DescriptionAttribute;

        return attribute == null ? value.ToString() : attribute.Description;
    }
}

关于c# - 在具有多个对应名称的枚举值上调用 ToString() 时,什么决定选择哪个名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12711059/

相关文章:

c# - 如何通过反射设置类的私有(private)成员的公共(public)字段的值?

枚举和 ConcurrentHashMap 上的 Java 单例。线程安全问题?

c++ - 编译时生成应在构造函数中创建的非 constexpr 对象的数组

c# - asp.net 从 jquery 代码生成函数

javascript - 服务器和浏览器日期差异

c# - 如何使用graph sdk而不是api在请求中传递$value以获取邮件的mime内容

.net - Enum 支持 Entity Framework 数据库优先

.NET 缓存 : maximum number of elements

java - 枚举内部类

c# - 使用 LINQ to Entities 生成不需要的请求