我希望以下调用Parse方法返回枚举成员EN_CA,但它会返回EN。
Enum.Parse(LanguageType, "EN_CA", true);
其中:
enum LanguageType
{
EN = 0,
EN_CA = 0,
FR = 1
}
似乎Parse方法只是抓取第一个映射到传递给它的参数值的成员.Parse方法在从字符串转换为枚举成员的过程中似乎丢失了信息。更改EN_CA和EN的顺序会使上述调用返回EN_CA,但这不会解决问题,因为在调用“EN”方法时会导致类似的问题。
其他与上下文相关的信息:在我的代码中,LanguageType Enum表示字典的索引,这些索引用于本地化语言。
有没有人知道如何将两个枚举成员映射到相同的值,同时能够从Enum.Parse获得适当的成员?我是否只需要实现我自己的Enum.Parse版本,它不会将具有相同值的成员合并为一个?
答案 0 :(得分:3)
枚举成员与其他枚举成员不同,如果仅,如果它具有不同的值。有效地,枚举的成员被命名为常量,除了它们持有的值之外,它们之间没有真正的区别。
在LanguageType
枚举中,您有两个相同值的标签,无法区分它们。试试这个:
Console.WriteLine("{0} == {1} ? {2}",
LanguageType.EN.ToString(),
LanguageType.EN_CA.ToString(),
LanguageType.EN == LanguageType.EN_CA);
输出结果为:
EN == EN ? True
将LanguageType.EN_CA
分配给变量时会发生同样的事情,然后稍后检查变量以查看它包含的内容。你得到的是LanguageType.EN
。
这里的关键是成员的值在大多数情况下都是非常重要的,其中成员的位置是冲突期间的决胜局。当两个成员具有相同的值时,首先声明的成员是您在进行字符串转换时将看到的成员,包括在IDE中检查值时。
因此,实际上您的值LanguageType.EN_CA
只是值LanguageType.EN
的别名。
虽然我可以想到几个可爱的用途 - 比如解析具有相同值的多个表示的传入数据 - 在大多数现实世界中做这件事真的很可怕环境,尤其是,如果您希望能够进行完全对称的序列化/反序列化。
现在,关于您的本地化Dictionary
...
在Dictionary中多次存储相同的类对象的成本非常低,因为类对象是通过引用存储的。假设您有一个Localization
类,以下代码在存储方面效率不是特别低:
enum LanguageType
{
EN, EN_CA, EN_US, EN_GB, EN_AU, FR
}
Dictionary<LanguageType, Localization> localizations = new Dictionary<LanguageType, Localization>();
localizations[LanguageType.EN] = new Localization("EN");
localizations[LanguageType.EN_CA] = localizations[LanguageType.EN];
localizations[LanguageType.EN_US] = localizations[LanguageType.EN];
localizations[LanguageType.EN_GB] = localizations[LanguageType.EN];
localizations[LanguageType.EN_AU] = localizations[LanguageType.EN];
即使Localization
对象包含大量资源,上面的代码也只创建了一个实例。您为LanguageType
成员获得了不同的值,而Dictionary
为您做了映射。
答案 1 :(得分:2)
您在枚举中定义了0
两次 - 这不起作用。每个值必须是唯一的,或者枚举如何识别其值 - 它实际上存储为整数。
将其更改为:
enum LanguageType
{
EN = 0,
EN_CA = 1,
FR = 2
}
修改强>:
正如Greenish所指出的,您可以为同一个值定义多个名称,作为一种别名。使用两个或多个名称将返回相同的值。如果您尝试从整数值获取字符串值,您将获得为该整数定义的第一个值。
在您的情况下,您无法使用枚举实现所需。你应该建立自己的自定义类来实现它。
答案 2 :(得分:1)
枚举基本上都是整数。并且可以为单个数字指定不同的名称(如示例中的0)。
Enum.Parse
搜索第一个正确的实例 - 此处您的有效名称为0 == 0
。所以解决方案是改变你的数字(甚至只是删除它们,因为它们是0,1,2)
enum LanguageType
{
EN,
EN_CA,
FR
}
答案 3 :(得分:1)
我想到了一种方式,但它是凌乱的脆弱和naff。它再次说明了你为自己挖的洞......
int index = Enum.GetNames(typeof(LanguageType)).indexof("EN_CA")
会给你1个
然后像
switch(index)
{
case 0 : return LanguageType.EN;
case 1 : return LangaugeType.EN_CA;
case 2 : return LanguageType.FR;
default : // throw some useful exception maybe
break
}
将返回您想要的成员。
可怕的不是吗?
Enum.GetValues(typeof(LanguageType))
将返回[0,0,1]并且使用indexof
0当然是0,这就是Parse为您提供结果的原因。
答案 4 :(得分:0)
=0
指定基础类型(int)中枚举值的表示。您已经为EN
和EN_CA
提供了相同的表示形式,即0,因此现在它们实际上已成为相同值的两个标签。
Enum.Parse
返回此值,它将等于两个标签。
潜在的问题是,您正在尝试将分层概念编码为扁平枚举。出于某些目的,所有英语国家的文化应该被平等对待,出于其他目的,你想区分它们。
我认为,解决方案是使用already present mechanisms for localizing your application,特别是CultureInfo应该替换您的枚举和Resources查找字典。
我有点惊讶,允许使用枚举:) 但MSDN documentation明确指出它是有效的,并举例说明它是如何有用的:
enum Color
{
Red,
Green,
Blue,
Max = Blue
}
答案 5 :(得分:0)
所以这就是我解决问题的方法:
我无法通过让Enum.Parse方法返回我期望的内容来找到问题的清晰修复。(请参阅注释*)
我的解决方法是在生成的字典上应用GroupBy(LanguageIndex)
,该字典的索引重复,因此抛出异常。因为我希望EN_CA和EN在枚举中具有相同的值,而不会抛出异常而给出了我想要的内容。
我可以看到我的修复不是我最初提出的问题的实际答案,而忽略了背景;虽然我可能仍然适用于具有类似问题的其他环境。
注意* :我本来可以实现我自己的Enum.Parse版本 - 请参阅 this 以获得替代实施的答案 - 但这需要我把臭硬编码的东西放进我的代码中,所以我放弃了修复Parse方法。