【问题标题】:Weird enum name resolution in C#C# 中奇怪的枚举名称解析
【发布时间】:2021-04-14 12:19:54
【问题描述】:

考虑以下代码:

using System;

namespace Test
{
    enum Foo
    {
        A = 1,
        B = 1,
        C = 1
    }
    
    public static class Program
    {
        public static void Main()
        {
            Console.WriteLine("{0}, {1}, {2}", Foo.A, Foo.B, Foo.C);
        }
    }
}

知道枚举只是底层的整数,我希望它是A, A, AC, C, C。但令人惊讶的是,它会打印出B, B, B!这种行为在 .NET Framework、.NET Core 3.x 和 .NET 5 中似乎是一致的。

为什么会选择B

【问题讨论】:

  • 你能解释一下为什么你期望这个构建的假设场景的输出是 A、A、A 还是 C、C、C?
  • 根据Enum.GetName()的文档是未定义的:If multiple enumeration members have the same underlying value, the GetName method guarantees that it will return the name of one of those enumeration members. However, it does not guarantee that it will always return the name of the same enumeration member. 所以它可以在这方面做它喜欢的事情。至于“为什么”,我想你得看看实现
  • 当你改变枚举中的顺序时,它仍然会打印第二个。
  • @FranzGleichmann 我希望枚举实现包含某种值到字符串的查找,其中包含第一个或最后一个声明

标签: c# .net enums


【解决方案1】:

根据 Enum.GetName() 的文档,它是未定义的:

如果多个枚举成员具有相同的基础值,则 GetName 方法保证它将返回其中之一的名称 枚举成员。但是,它不保证它会 总是返回同一个枚举成员的名字。

所以在这方面它可以为所欲为。

至于为什么在你的例子中它返回B,我们可以检查GetEnumName()的实现:

public virtual string GetEnumName(object value)
{
    if (value == null)
        throw new ArgumentNullException("value");

    if (!IsEnum)
        throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
    Contract.EndContractBlock();

    Type valueType = value.GetType();

    if (!(valueType.IsEnum || Type.IsIntegerType(valueType)))
        throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnumBaseTypeOrEnum"), "value");

    Array values = GetEnumRawConstantValues();
    int index = BinarySearch(values, value);

    if (index >= 0)
    {
        string[] names = GetEnumNames();
        return names[index];
    }

    return null;
}

啊哈!一切都解释清楚了。为了加快查找速度,他们使用了二分查找。开始搜索时,二分搜索首先查找的位置在哪里?没错 - 它从列表的一半开始。这就是为什么它首先找到B - 在列表排序之后,B 在中间。

(请注意,列表是按枚举值排序的,而不是枚举名称,因此对于您的情况,列表已经排序,因为所有值都相同。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多