为什么Enum.TryParse需要约束,其中T:struct

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么Enum.TryParse需要约束,其中T:struct相关的知识,希望对你有一定的参考价值。

我试图了解一种扩展方法将string转换为Enum找到here

public static T ToEnum<T>(this string value, T defaultValue)
{
     if (string.IsNullOrEmpty(value))
     {
        return defaultValue;
     }

     T result;
     return Enum.TryParse<T>(value, true, out result) ? result : defaultValue;
}

编译错误:

类型'T'必须是非可空值类型才能在泛型类型或方法'Enum.TryParse(string,bool,out TEnum)'中将其用作参数'TEnum'

其中一个评论说要添加where T : struct以使扩展方法起作用。

约束方法:

public static T ToEnum<T>(this string value, T defaultValue) where T : struct
{
    if (string.IsNullOrEmpty(value))
    {
          return defaultValue;
    }

    T result;
    return Enum.TryParse<T>(value, true, out result) ? result : defaultValue;
}

我阅读了关于Enum.TryParse的文档,但我在文档中并不理解为什么添加where T : struct作为类型T的约束?

为什么上面的扩展不会没有约束,因为struct为什么不是其他值类型?如何联系structEnum类型?或者它只是一种语法?

更新:

他们中的大多数说可以使用任何值类型,我试图使用where T : int但我得到编译时错误:

'int'不是有效的约束。用作约束的类型必须是接口,非密封类或类型参数。

答案

约束struct不仅包括您通过struct MyStruct声明的类型,还包括许多内置类型,如intbytechar。实际上约束将T限制为任何值类型,请参阅C#-specification 9.4.5 Satisfying constraints

如果约束是值类型约束(struct),则类型A应满足以下之一

  • A是结构类型或枚举类型,但不是可空值类型。 [注意:System.ValueType和System.Enum是不满足此约束的引用类型。结束说明]
  • A是具有值类型约束的类型参数(第15.2.5节)

当然,如果存在更严格的约束,那将是很好的。

在编辑时:在这种情况下,您的编译器消息非常清楚。使用类型作为约束时,您只能使用接口或非密封类。限制泛型类型参数以恰好匹配一个单独的类(或结构)会使泛型非常无用,不是吗?将您的泛型限制为int将有效地将您的方法签名转换为如下所示:

public static int ToEnum(this string value, int defaultValue)

因为只有一个结构匹配约束。

另一答案

这样做是为了在编译时启用部分错误检查:

  • 引用类型在编译时被拒绝,
  • 不是enums的值类型在运行时被拒绝。

如果你能编写where T : Enum会更好,但C#编译器禁止这样做:

约束不能是特殊类`System.Enum'

有关此错误的更多信息,请访问see this Q&A。特别是,请参阅this answer以简要解决问题。

以上是关于为什么Enum.TryParse需要约束,其中T:struct的主要内容,如果未能解决你的问题,请参考以下文章

带有标志属性的 Enum.TryParse

`<T extends E>` 形式的通用约束,其中`E` 是`enum`?

当其中一个是本地引用时,如何为类型约束中的引用编写生命周期?

通用约束,其中 T : struct 和 where T : class

如何删除重复条目?

枚举常用