C#:即使枚举不包含该值,Enum.TryParse() 在传递“-1”时也会成功

mik*_*l98 2 c# enums

我只想在正确解析枚举的值时才打印它。如Enum.TryParse()文档中所述:

将一个或多个枚举常量的名称或数值的字符串表示形式转换为等效的枚举对象。返回值表示转换是否成功。

如果转换成功则返回
Boolean ;否则。
truefalse

现在,考虑下面的示例,我希望仅当我尝试解析像"first"or 这样的字符串"1"(它们是 的名称/值)时,调用才会成功TestEnum

但是如果我尝试解析 string "-1",调用仍然成功并且我得到-1值,这怎么可能?

例子:

using System;

public class HelloWorld
{
    public enum TestEnum
    {
        first = 0,
        second = 1,
        third = 2
    }
    
    public static void Main(string[] args)
    {
        TestEnum testEnum;
        bool res;
        
        res = Enum.TryParse("first", out testEnum);
        if (res)
            Console.WriteLine ("TEST 1 - res: " + res.ToString() + ", value: " + testEnum.ToString());
            
        res = Enum.TryParse("third", out testEnum);
        if (res)
            Console.WriteLine ("TEST 2 - res: " + res.ToString() + ", value: " + testEnum.ToString());
            
        res = Enum.TryParse("1", out testEnum);
        if (res)
            Console.WriteLine ("TEST 3 - res: " + res.ToString() + ", value: " + testEnum.ToString());
            
        
        res = Enum.TryParse("-1", out testEnum);
        if (res)
            Console.WriteLine ("TEST 4 - res: " + res.ToString() + ", value: " + testEnum.ToString());
            
        res = Enum.TryParse("fourth", out testEnum);
        if (res)
            Console.WriteLine ("TEST 5 - res: " + res.ToString() + ", value: " + testEnum.ToString());
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

TEST 1 - res: True, value: first
TEST 2 - res: True, value: third
TEST 3 - res: True, value: second
TEST 4 - res: True, value: -1        // <-- How??
Run Code Online (Sandbox Code Playgroud)

代码链接: https: //onlinegdb.com/1MIOnOFl6

Som*_*ody 6

实际上,枚举是一个整数,可以保存普通整数可以保存的所有值。就你而言,

TestEnum test1 = TestEnum.first;
Run Code Online (Sandbox Code Playgroud)

将创建一个值为 0 的整数。但也可以创建一个变量

TestEnum test2 = (TestEnum)-1;
Run Code Online (Sandbox Code Playgroud)

因为-1是一个有效的整数并且可以赋值给TestEnum。这也是为什么如果您使用带有枚举的开关,通常会编写这样的代码:

switch(test)
{
   case TestEnum.first: DoSomething(); break;
   case TestEnum.second: DoSomethingElse(); break;
   case TestEnum.third: DoSomethingDifferent(); break;
   default: throw new Exception("invalid value for test");
}
Run Code Online (Sandbox Code Playgroud)

您需要 default 子句,因为您不能相信您的枚举变量只是第一、第二或第三值之一。

您还可以更改枚举的基础类型。例如,如果您像这样声明您的枚举

public enum TestEnum : uint { first = 0, second = 1, third= 2}
Run Code Online (Sandbox Code Playgroud)

上面的赋值将无效(因为 -1 不是 的有效值uint。此外, res = Enum.TryParse("-1", out testEnum);在这种情况下将返回 false。

如果您想知道为什么这种行为有意义,请考虑带有 flags 选项的枚举:

[Flags]
public enum Options
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option4 = 8
}
Run Code Online (Sandbox Code Playgroud)

这里你可以写Options options = Options.Option1 | Options.Option2,它的值为 3 ,但上面的枚举中没有定义。

正如注释中所述,Enum.IsDefined如果您想检查该值是否真正定义,可以使用该方法。您可以检查枚举中是否定义了数值或字符串。