C# 为什么Enum.Parse会创建未定义的条目?
如果执行上面的代码,结果显示: 你应该每天至少吃一个12345 如果传递了未知名称(字符串),我真的希望抛出ArgumentException。仔细查看Enum.Parse定义可以发现: 摘要:C# 为什么Enum.Parse会创建未定义的条目?,c#,.net,enums,behavior,C#,.net,Enums,Behavior,如果执行上面的代码,结果显示: 你应该每天至少吃一个12345 如果传递了未知名称(字符串),我真的希望抛出ArgumentException。仔细查看Enum.Parse定义可以发现: 摘要: 将一个或多个枚举常量的名称或数值的字符串表示形式转换为等效的枚举对象 例外情况: ArgumentException:enumType不是枚举-或-value为空字符串或仅包含空格-或者-值是一个名称,但不是为枚举定义的命名常量之一 也就是说,如果传递了整数的字符串表示形式,则会创建一个新的枚举值,现在
将一个或多个枚举常量的名称或数值的字符串表示形式转换为等效的枚举对象 例外情况:
ArgumentException:enumType不是枚举-或-value为空字符串或仅包含空格-或者-值是一个名称,但不是为枚举定义的命名常量之一 也就是说,如果传递了整数的字符串表示形式,则会创建一个新的枚举值,现在设计会引发异常。这有意义吗
至少我现在知道在
Enum.Parse()之前调用Enum.IsDefined(enumType,value)
,您需要使用Enum.IsDefined:
我个人认为很遗憾,Enum.Parse
接受数字的字符串表示。如果您正在寻找替代方案,您可能希望查看我的项目,它有各种解析选项,并且也是强类型的
您当然可以将Enum.IsDefined
与解析结合使用。但是,您确实想要接受数字的字符串版本吗?或者您真的只需要名称吗?命名常量是枚举值的文本表示,而不是您分配给它的数字
如果您更改:
using System;
[Flags] enum Colors { None=0, Red = 1, Green = 2, Blue = 4 };
public class Example
{
public static void Main()
{
string[] colorStrings = { "0", "2", "8", "blue", "Blue", "Yellow", "Red, Green" };
foreach (string colorString in colorStrings)
{
try {
Colors colorValue = (Colors) Enum.Parse(typeof(Colors), colorString);
if (Enum.IsDefined(typeof(Colors), colorValue) | colorValue.ToString().Contains(","))
Console.WriteLine("Converted '{0}' to {1}.", colorString, colorValue.ToString());
else
Console.WriteLine("{0} is not an underlying value of the Colors enumeration.", colorString);
}
catch (ArgumentException) {
Console.WriteLine("'{0}' is not a member of the Colors enumeration.", colorString);
}
}
}
}
// The example displays the following output:
// Converted '0' to None.
// Converted '2' to Green.
// 8 is not an underlying value of the Colors enumeration.
// 'blue' is not a member of the Colors enumeration.
// Converted 'Blue' to Blue.
// 'Yellow' is not a member of the Colors enumeration.
// Converted 'Red, Green' to Red, Green.
致:
您将看到预期的错误,因为“value是一个名称,但不是为枚举定义的命名常量之一。”。在本例中,传递的值是一个名称“Cake”,但不是枚举中的名称
想想Enum.Parse(enumType,value)代码>执行以下操作:
如果value
是空引用,则抛出ArgumentNullException
value
中的值是enumType
中枚举中的命名常量之一。如果是,则从枚举返回该值并停止
value
中的值是否可直接转换为基础类型(在本例中为Int32),如果是,则返回该值并停止(,即使该值没有命名常量)
value
中的值是否可直接转换为基础类型,但不在基础类型的范围内?e、 g.该值是一个包含大于MAXINT的数字1的字符串。如果是,则抛出一个OverflowException
该值是否不可强制转换到基础类型?如果是,则抛出ArgumentException
枚举可以是其基整数类型的任何值。它不仅限于命名常量
例如,以下内容完全有效:
string value = "Cake";
即使5与命名常量不对应,它仍然是Foo
的有效值,因为Foo
的基础类型是Int32
如果调用x.ToString()
,返回的值将只是“5”,因为没有命名常量与x的值对应
Enum.Parse()
是Enum.ToString()
的反函数。您应该期望无论什么Enum.ToString()
都可以返回Enum.Parse()
可以接受的值。例如,这包括标志枚举的逗号分隔值:
enum Foo{
A,
B,
C,
D
}
Foo x = (Foo)5;
输出:
[Flags]
enum Foo{
A = 1,
B = 2,
C = 4,
D = 8
}
Foo x = Foo.A | Foo.B | Foo.C | Foo.D;
int i = (int)x;
string s = x.ToString();
Console.WriteLine(i);
Console.WriteLine(s);
Console.WriteLine((Foo)Enum.Parse(typeof(Foo), i.ToString()) == x);
Console.WriteLine((Foo)Enum.Parse(typeof(Foo), s) == x);
15
A、 B、C、D
真的
真的
编辑:
你真正想要的是这样的东西:
15
A, B, C, D
True
True
静态枚举GetEnumValue(类型enumType,字符串名称){
//为简洁起见,省略了空检查
int index=Array.IndexOf(Enum.GetNames(enumType),name);
如果(指数<0)
抛出新ArgumentException(“\”+name+“\”不是“+enumType,“name”中的值);
返回Enum.GetValues(enumType).GetValue(索引);
}
或不区分大小写的版本:
static Enum GetEnumValue(Type enumType, string name){
// null-checking omitted for brevity
int index = Array.IndexOf(Enum.GetNames(enumType), name);
if(index < 0)
throw new ArgumentException("\"" + name + "\" is not a value in " + enumType, "name");
return Enum.GetValues(enumType).GetValue(index);
}
静态枚举GetEnumValue(类型enumType、字符串名称、bool ignoreCase){
//省略空检查
整数指数;
如果(忽略案例)
index=Array.FindIndex(Enum.GetNames(enumType),
s=>string.Compare(s,name,StringComparison.OrdinalIgnoreCase)==0);
//或者StringComparison.CurrentCultureInogoreCase或者其他什么
//需要支持花哨的Unicode名称吗
else index=Array.IndexOf(Enum.GetNames(enumType),name);
如果(指数<0)
抛出新ArgumentException(“\”+name+“\”不是“+enumType,“name”中的值);
返回Enum.GetValues(enumType).GetValue(索引);
}
你为什么要问和回答你自己的问题?这个问题是关于行为的……希望我在回答中以一种有意义的方式解释了行为(或我对行为的解释)。如果它不让我知道,我会看看我能做些什么来解决它=)是的,我知道,但我不明白为什么Enum.Parse会生成新值,这就像调用Int.Parse(“人类不知道的大数字”)并得到一个结果……你是对的,因为Enum是一个Int32 Enum。Parse(“”)返回有效值是正确的。我的问题是由于将Enum视为一个收缩的Int32而引起的,实际上它不是。严格来说,这是不正确的。字符串永远不能“转换”为int,它需要通过多种方法进行转换(Convert.ToInt32
,int.Parse
,int.TryParse
,等等)。更准确的表达式3.)是“值中的值是否可直接转换为基础类型(在本例中为Int32
)?如果是,则返回该值并停止(即使该值没有命名常量)真的很遗憾,<代码>枚举>解析> <代码>接受一个数字的字符串表示吗?如果没有,我会认为它是坏的,因为这意味着枚举VA。
15
A, B, C, D
True
True
static Enum GetEnumValue(Type enumType, string name){
// null-checking omitted for brevity
int index = Array.IndexOf(Enum.GetNames(enumType), name);
if(index < 0)
throw new ArgumentException("\"" + name + "\" is not a value in " + enumType, "name");
return Enum.GetValues(enumType).GetValue(index);
}
static Enum GetEnumValue(Type enumType, string name, bool ignoreCase){
// null-checking omitted
int index;
if(ignoreCase)
index = Array.FindIndex(Enum.GetNames(enumType),
s => string.Compare(s, name, StringComparison.OrdinalIgnoreCase) == 0);
// or StringComparison.CurrentCultureIgnoreCase or something if you
// need to support fancy Unicode names
else index = Array.IndexOf(Enum.GetNames(enumType), name);
if(index < 0)
throw new ArgumentException("\"" + name + "\" is not a value in " + enumType, "name");
return Enum.GetValues(enumType).GetValue(index);
}