【问题标题】:C# Enum.TryParse parses invalid number stringsC# Enum.TryParse 解析无效数字字符串
【发布时间】:2016-01-31 17:59:10
【问题描述】:

C# .NET 4.5,Windows 10,我有以下枚举:

private enum Enums
{
    A=1, B=2, C=3
}

而且这个程序的行为方式非常奇怪:

public static void Main()
{
    Enums e;
    if (Enum.TryParse("12", out e))
    {
        Console.WriteLine("Parsed {0}", e);
    }
    else
    {
        Console.Write("Not parsed");
    }
    Console.ReadLine();
}

我希望 TryParse 方法的结果是错误的,但令我惊讶的是 控制台显示“Parsed 12”。 在 Watch 窗口中,它甚至显示值为“12”并且它是 Enums 类型!

这适用于我尝试过的任何数字字符串(例如“540”),但不适用于包含字母的字符串(“A12”、“12A”)。

我可以通过首先检查它是否是纯数字字符串来轻松克服这个问题,但为什么会出现这种情况? 是设计的吗?

谢谢! 伊多

【问题讨论】:

  • 是的,这是设计使然。如果一个值上的.ToString() 可以返回一个特定的字符串,并且所讨论的类型有一个.Parse() 方法,那么解析方法应该接受该字符串作为返回,这是一个好主意。由于枚举可以保存“未知”值(即枚举中没有名称的值),并且.ToString() 会将这些值作为字符串中的数字返回,因此.Parse() 应该接受一个字符串保存只有一个整数。所以是的,这是设计使然。您可能不同意这个决定,但事实就是如此。

标签: c# enums


【解决方案1】:

在内部,枚举被存储为整数,所以这很可能是 TryParse 对传入的整数返回 true 的原因。

关于为什么任何整数都有效,这是设计使然。来自MSDN(强调我的):

当此方法返回时,结果包含一个 TEnum 类型的对象 如果解析操作成功,则其值由 value 表示。 如果解析操作失败,结果包含默认值 TEnum 的基础类型。 请注意,此值不必是 TEnum 枚举。此参数未初始化传递。

【讨论】:

  • 谢谢!我没有找对地方。另外,显然来自 MSDN:如果这种行为是不可取的,请调用 IsDefined 方法以确保整数的特定字符串表示实际上是 TEnum 的成员。
  • 不客气。是的,如果有可能传入非成员整数,使用IsDefined 会有所帮助。您可以创建一个扩展方法,在解析后为您处理IsDefined 检查,以便您可以使用该方法而不是默认TryParse
【解决方案2】:

枚举类型的变量或字段可以保存其基础类型的任何值,因此在您的情况下将值 12 存储在 Enums 类型的变量中是完全合法的:

var e = (Enums) 12;
var i = (int) e; // i is 12

因此,Enum.TryParse 必须能够解析int 类型的任何值(或枚举中使用的任何底层整数类型)。

如果您想拒绝枚举中没有表示的值,请使用Enum.IsDefined 进行检查。

【讨论】:

    【解决方案3】:

    此方法将整数严格解析到枚举的范围内:

    public static bool EnumTryParseStrict<TEnum>(string value, out TEnum result, bool ignoreCase = false) where TEnum : struct, Enum {
            if (Enum.TryParse(value, ignoreCase, out result) && Enum.IsDefined(typeof(TEnum), result)) {
                return true;
            }
            result = default;
            return false;
    }
    

    【讨论】:

    • 这行得通,但它打破了 Enum.TryParse 合约设定的期望:“如果解析操作失败,结果包含 TEnum 底层类型的默认值”
    • 如果严格解析操作失败,result现在包含TEnum底层类型的默认值。
    猜你喜欢
    • 1970-01-01
    • 2021-05-08
    • 1970-01-01
    • 2023-04-10
    • 2015-03-23
    • 2017-03-02
    • 2021-06-03
    • 1970-01-01
    • 2015-12-06
    相关资源
    最近更新 更多