Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么Enum.Parse会创建未定义的条目?_C#_.net_Enums_Behavior - Fatal编程技术网

C# 为什么Enum.Parse会创建未定义的条目?

C# 为什么Enum.Parse会创建未定义的条目?,c#,.net,enums,behavior,C#,.net,Enums,Behavior,如果执行上面的代码,结果显示: 你应该每天至少吃一个12345 如果传递未知名称字符串,我真的希望抛出ArgumentException。仔细查看Enum.Parse定义可以发现: 总结: 将一个或多个枚举常量的名称或数值的字符串表示形式转换为等效的枚举对象 例外情况: ArgumentException:enumType不是枚举-或-value为空字符串或仅包含空格-或-value是名称,但不是为枚举定义的命名常量之一 也就是说,如果传递了整数的字符串表示形式,则会创建一个新的枚举值,现在设计

如果执行上面的代码,结果显示:

你应该每天至少吃一个12345

如果传递未知名称字符串,我真的希望抛出ArgumentException。仔细查看Enum.Parse定义可以发现:

总结: 将一个或多个枚举常量的名称或数值的字符串表示形式转换为等效的枚举对象

例外情况: ArgumentException:enumType不是枚举-或-value为空字符串或仅包含空格-或-value是名称,但不是为枚举定义的命名常量之一

也就是说,如果传递了整数的字符串表示形式,则会创建一个新的枚举值,现在设计会引发异常。这有意义吗


至少我现在知道要调用Enum.IsDefinedenumType,即Enum.Parse之前的值

您需要使用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.ParseenumType,value;执行以下操作:

如果值是空引用,则引发ArgumentNullException 是枚举类型中枚举中的命名常量之一的值。如果是,则从枚举返回该值并停止。 value中的值是否可直接转换为此实例Int32中的基础类型,如果是,则返回该值并停止,即使该值没有命名常量。 值中的值是否可直接转换为基础类型,但不在基础类型的范围内?e、 g.该值是一个包含大于MAXINT的数字1的字符串。如果是,抛出OverflowException。 该值是否不可强制转换到基础类型?如果是,则抛出ArgumentException。
枚举可以是其基整数类型的任何值。它不仅限于命名常量

例如,以下内容完全有效:

string value = "Cake";
尽管5与命名常量不对应,但它仍然是Foo的有效值,因为Foo的底层类型是Int32

如果调用x.ToString,返回值将仅为5,因为没有命名常量与x的值对应

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 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);
}

你为什么要问和回答你自己的问题?这个问题是关于行为的…希望我已经在我的回答中以一种有意义的方式解释了行为或我对它的解释。如果它不让我知道,我会看看我能做些什么来解决它=是的,我知道,但我不明白为什么Enum.Parse会生成新的值,这就像调用Int.Parsebig number(人类不知道)并得到一个结果……你是对的,因为Enum是一个Int32 Enum。Parse返回有效值是正确的。我的问题是由于将Enum视为一个收缩的Int32而引起的,实际上它不是。严格来说,这是不正确的。字符串永远不能转换为int,它需要通过多种方法进行转换Convert.ToInt32、int.Parse、int.TryParse等。。3的更精确表达式。值中的值是否可直接转换为此实例Int32中的基础类型?如果是,则返回该值并停止,即使该值没有命名常量。Enum.Parse接受数字的字符串表示真的很遗憾吗?如果没有,我会认为它被破坏了,因为这意味着枚举值可能不是往返于一个字符串中,也就是枚举。PARSEOVALVALUES.ToString可能失败。感谢EnUn.PARSE和ToString的额外了解,我不知道具有逗号分隔值的特性。 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);
}