如果我在C#枚举中有重复值,请说
enum MyE {
value1 = 1,
value2 = 2,
valued = 1
}
以下字符串的值应该是什么?
MyE N = (MyE)1;
string V1 = N.ToString();
string V2 = GetName(MyE, 1);
V1和V2必须包含相同的值吗? 这些价值应该是什么?
我没有在MSDN中找到任何内容,或者在这里有关于重复的枚举的“解除引用”,请指出我的链接,如果我错过了。
答案 0 :(得分:15)
实验表明:
V1 =“value1”
和
V2 =“value1”
但是,这不能保证。 MSDN page on Enum.GetName
州:
如果多个枚举成员具有相同的基础值,则GetName方法保证它将返回其中一个枚举成员的名称。但是,它不保证它始终返回相同枚举成员的名称。因此,当多个枚举成员具有相同的值时,您的应用程序代码永远不应该依赖于返回特定成员名称的方法。
答案 1 :(得分:2)
在Enum.GetName
方法文档(http://msdn.microsoft.com/en-us/library/system.enum.getname.aspx)的“备注”部分中,它说:
如果多个枚举成员具有相同的基础值,则GetName方法保证它将返回其中一个枚举成员的名称。但是,它不保证它始终返回相同枚举成员的名称。因此,当多个枚举成员具有相同的值时,您的应用程序代码永远不应该依赖于返回特定成员名称的方法。
我运行测试以查看实验会发生什么,并且它总是返回定义的第一个值(在您的示例中为value1),但根据上面的官方文档,您不能依赖 (参见@ gluk47的评论,表明野外的不同行为)。
答案 2 :(得分:1)
我不同意其他答案声明
......这不是保证......
...你不能依赖 ......
以及msdn声明:
...您的应用程序代码永远不应该依赖于返回特定成员名称的方法......
我的软件中有一个枚举
enum Blabla { A = 0, B = 1, C = 2, D = 3 }
某些时候A
值更改为AA
,后来AA
更改为AAA
。为了保持向后兼容,我不得不这样做
enum Blabla { A = 0, AA = 0, AAA = 0, B = 1, C = 2, D = 3 }
这允许将旧的枚举值(由旧版软件制作)反序列化为AAA
。
然后有一个报告打印Blabla
设置值。在某些时候,每个使用新版本的客户都会开始告诉我他们看到AAA
值AA
而不是AA
。所有人都看到A
(没有人报告AAA
)。
我做了什么?我只是更改顺序(直到结果为enum Blabla { AAA = 0, A = 0, AA = 0, ...}
)
Blabla.AAA
并进行了测试,以确保将AAA
输出为Enum.ToString()
。问题解决了吗?
查看Enum.GetName()
(或Array.BinarySearch()
)的来源,它使用GetEnumName(),它调用enum
来排序值的数组以查找值的索引。
二元搜索的结果是 deterministic :为其提供相同的参数将返回相同的结果。
所以:
Enum.ToString()
格式将被更改(例如,定义顺序和值列表顺序不同)或else
将被更改,但它可能会发生,因此请确保你对依赖返回值的情况进行测试。答案 3 :(得分:0)
好吧,因为无法保证订单和过时的属性似乎对Enum
方法没有影响,我通常会建议使用字符串属性进行序列化,并使用自定义代码来处理过时的值。
这样,主Enum
没有重复,只包含当前值。
根据序列化框架,您可以将字符串属性标记为可序列化但过时,并且序列化将忽略代码中使用的实际属性。
要处理字符串属性设置器中的过时值,可以使用[Obsolete] enum
或switch语句。通常,我可能会使用前者,如果我有很多过时的值来处理,后者如果我只有几个值可以处理。
将代码放在辅助类或扩展方法中也是有意义的,特别是如果从一堆地方加载或存储该值。
虽然我在生产代码中没有尝试过多,但我想知道使用struct
代替enum
来控制更多内容是否更好......但我认为需要许多样板代码不能轻易通用。
答案 4 :(得分:0)
虽然这对党来说可能有点晚了,但这可能不是一个好主意,但是,在我不得不使用重复枚举的情况下,我确实找到了一个解决方法,那就是使用这里的问题; Get String Name from Enum in C#
var name = nameof(DeclaredEnum.EnumName);
结果:
EnumName
您可以阅读更多Here,了解其实际工作原理。