Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.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为空字符串或仅包含空格-或者-值是一个名称,但不是为枚举定义的命名常量之一 也就是说,如果传递了整数的字符串表示形式,则会创建一个新的枚举值,现在

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

你应该每天至少吃一个12345

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

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

例外情况:
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);
    }