首页 文章

C#中的枚举类型约束[重复]

提问于
浏览
147

可能重复:任何人都知道缺少枚举通用约束的良好解决方法?

C#不允许对 Enum 's? I'进行类型约束的原因是什么?我确定疯狂背后有一种方法,但是我不能实现.1006802_ .

以下是我希望能够做到的(理论上) .

public static T GetEnum<T>(this string description) where T : Enum
{
...
}

6 回答

  • 3

    这是偶尔要求的功能 .

    正如我喜欢指出的那样,所有功能都没有实现,直到有人设计,规格,工具,测试,文档和发布功能 . 到目前为止,还没有人为此做过 . 没有特别不寻常的原因;我们还有很多其他的事情要做,预算有限,而且这个从来没有超过“这不是很好吗?”语言设计团队的讨论 .

    CLR不支持它,所以为了使它工作,除了语言工作之外,我们还需要做运行时工作 . (见答复评论)

    我可以看到有一些不错的使用案例,但没有一个是如此引人注目,以至于我们做了这项工作,而不是更频繁要求的数百个其他功能之一,或者更具吸引力和更进一步的功能用例 . (如果我们要使用这段代码,我会亲自优先考虑委托约束方式,比上面的枚举约束 . )

  • 2

    实际上,这可能是一个丑陋的伎俩 . 但是,它不能用于扩展方法 .

    public abstract class Enums<Temp> where Temp : class {
        public static TEnum Parse<TEnum>(string name) where TEnum : struct, Temp {
            return (TEnum)Enum.Parse(typeof(TEnum), name); 
        }
    }
    public abstract class Enums : Enums<Enum> { }
    
    Enums.Parse<DateTimeKind>("Local")
    

    如果你愿意,可以给 Enums<Temp> 一个私有构造函数和一个公共嵌套的抽象继承类, TempEnum ,以防止非枚举的继承版本 .

    请注意,您不能使用此技巧来制作扩展方法 .

  • 14
    public static T GetEnum<T>(this string description) where T : struct
    {
        return (T)Enum.Parse(typeof(T), description);
    }
    

    它能回答你的问题吗?

  • 144

    IL编织使用ExtraConstraints

    您的密码

    public static T GetEnum<[EnumConstraint] T>(this string description)
    {
        ...
    }
    

    什么被编译

    public static T GetEnum<T>(this string description) where T : Enum
    {
        ...
    }
    
  • 92

    这是SLaks excellent ugly trick的VB.NET版本, Imports 为"typedef" :(类型推断按预期工作,但您无法获得扩展方法 . )

    'Base namespace "EnumConstraint"
    Imports Enums = EnumConstraint.Enums(Of System.Enum)
    
    Public NotInheritable Class Enums(Of Temp As Class)
    Private Sub New()
    End Sub
    
    Public Shared Function Parse(Of TEnum As {Temp, Structure})(ByVal Name As String) As TEnum
        Return DirectCast([Enum].Parse(GetType(TEnum), Name), TEnum)
    End Function
    
    Public Shared Function IsDefined(Of TEnum As {Temp, Structure})(ByVal Value As TEnum) As Boolean
        Return [Enum].IsDefined(GetType(TEnum), Value)
    End Function
    
    Public Shared Function HasFlags(Of TEnum As {Temp, Structure})(ByVal Value As TEnum, ByVal Flags As TEnum) As Boolean
        Dim flags64 As Long = Convert.ToInt64(Flags)
        Return (Convert.ToInt64(Value) And flags64) = flags64
    End Function
    
    End Class
    
    Module Module1
    
    Sub Main()
    
        Dim k = Enums.Parse(Of DateTimeKind)("Local")
        Console.WriteLine("{0} = {1}", k, CInt(k))
        Console.WriteLine("IsDefined({0}) = {1}", k, Enums.IsDefined(k))
        k = DirectCast(k * 2, DateTimeKind)
        Console.WriteLine("IsDefined({0}) = {1}", k, Enums.IsDefined(k))
    
        Console.WriteLine(" {0} same as {1} Or {2}: {3} ", IO.FileAccess.ReadWrite, IO.FileAccess.Read, IO.FileAccess.Write, _
                          Enums.HasFlags(IO.FileAccess.ReadWrite, IO.FileAccess.Read Or IO.FileAccess.Write))
    
        ' These fail to compile as expected:
        'Console.WriteLine(Enums.HasFlags(IO.FileAccess.ReadWrite, IO.FileOptions.RandomAccess))
        'Console.WriteLine(Enums.HasFlags(Of IO.FileAccess)(IO.FileAccess.ReadWrite, IO.FileOptions.RandomAccess))
    
        If Debugger.IsAttached Then _
            Console.ReadLine()
    End Sub
    
    End Module
    

    输出:

    Local = 2
    IsDefined(Local) = True
    IsDefined(4) = False
     ReadWrite same as Read Or Write: True
    
  • 4

    这里有一个古怪的事情是,你可能想要编写相当多的通用枚举方法,其实现取决于枚举的“基本”类型 .

    通过"base"类型的枚举 E ,我的意思是 System 命名空间中的类型,其名称与通过调用System.Type.GetTypeCode(System.Type)类型 E 获得的 System.TypeCode 枚举成员的名称相同 . 如果枚举是在C#中声明的,那么它与从"inherit"声明的类型相同(我不确定这是在规范中正式调用的) . 例如,以下 Animal 枚举的基本类型是 System.Byte

    public enum Animal : byte
    {
        Moose,
        Squirrel
    }
    

    可以使用switch语句编写这样的方法,但肯定是丑陋的,你不能获得强类型参数或类型是枚举的基类型的返回类型,你必须重复元数据查找或做一些缓存(例如,在包含该方法的泛型类型的静态构造函数中) .

相关问题