我正在使用枚举循环引用将一些现有的枚举归结为更少的值。它对我的问题很有效,因为它是一个过渡期,旧的枚举值确实出现在历史中,但不会创建具有过时值的新条目。
我不是在寻找替代方法,但我偶然发现了这个奇怪的问题,其中枚举的顺序会以意想不到的方式影响序列化值。
我有这个枚举:
public enum CivilStatusEnum
{
None = 0,
Married = 1,
Cohabiting = Married,
Alone = 3,
DivorcedOrSeparated = Alone,
WidowOrWidower = Alone,
}
Run Code Online (Sandbox Code Playgroud)
我分配了“DivorcedOrSeparated”= Alone (3)。现在,当我将枚举转换为字符串时,我得到值“DivorcedOrSeparated”。
Console.PrintLine(CivilStatusEnum.Alone.ToString());
Run Code Online (Sandbox Code Playgroud)
输出:
DivorcedOrSeparated
Run Code Online (Sandbox Code Playgroud)
我有一个示例代码,其中包含测试及其预期结果。如您所见,测试失败。但是如果我改变枚举的顺序,测试就会解析。
[Theory]
[InlineData(CivilStatusEnum.Alone, "Alone")]
[InlineData(CivilStatusEnum.DivorcedOrSeparated, "Alone")]
[InlineData(CivilStatusEnum.WidowOrWidower, "Alone")]
[InlineData(CivilStatusEnum.None, "None")]
[InlineData(CivilStatusEnum.Married, "Married")]
[InlineData(CivilStatusEnum.Cohabiting, "Married")]
public void Test(CivilStatusEnum input, string expected)
{
var text = input.ToString();
text.Should().Be(expected);
}
Run Code Online (Sandbox Code Playgroud)
我似乎无法找到一个合理的解释,说明为什么顺序对 tostring 和 serilization 很重要。
这是 .NET 5 中的错误,还是我遗漏了什么?如果这种行为是故意的,它如何确定哪个枚举名称将是 tostring 的输出?
谢谢 :)
Enum.ToString
执行二分查找。
实际上,ToString调用InternalFormat,后者调用GetEnumName。该方法在 EnumInfo.Values 返回的数组中执行二分搜索。
我假设数组以基础值的递增顺序填充(否则二进制搜索将不起作用),并且如果它们相等,则以在源代码中声明的值的顺序填充。这使得搜索结果依赖于声明的顺序。
为了说明这种二分搜索的效果,请考虑以下两个enum
定义:
enum Test1 { A = 0, B = 0, C = 0 }
enum Test2 { A = 0, B = 0, C = 0, D = 0, E = 0 }
Run Code Online (Sandbox Code Playgroud)
会是什么结果Test1.A.ToString()
?需要注意的是值Test1.A
是0
。二分查找将首先考虑列表中间的元素,它B
的值为0
。该值等于我们正在搜索的值,因此Test1.A.ToString()
返回"B"
。如果找到的值高于正在搜索的值,搜索将在列表的下半部分继续。如果找到的值低于正在搜索的值,则搜索将在列表的上半部分继续。
枚举中的所有常量也是如此,因为它们都具有相同的值。所以,Test1.C.ToString()
同样会返回"B"
。
同样,如预期的那样Test2.A.ToString()
返回"C"
。
但是请注意,虽然此行为在 .NET 的当前版本中似乎是可以预测的,但它是undefined,并且可能会在未来版本中更改。
这不是 .NET 5 中的错误。 毕竟,以下两种情况都不可能为真:
CivilStatusEnum.Alone.ToString() == "Alone"
CivilStatusEnum.DivorcedOrSeparated.ToString() == "DivorcedOrSeparated"
Run Code Online (Sandbox Code Playgroud)
原因当然是CivilStatusEnum.Alone == CivilStatusEnum.DivorcedOrSeparated
。
以下是文档对此的说明:
如果多个枚举成员具有相同的基础值,并且您尝试根据其基础值检索枚举成员名称的字符串表示形式,则您的代码不应假设该方法将返回哪个名称。
归档时间: |
|
查看次数: |
68 次 |
最近记录: |