通用T与枚举和铸造T到枚举

Raf*_*afe 5 .net generics enums casting constraints

我四处搜索,找不到任何这样做的例子,虽然这很有帮助:

创建将T限制为枚举的通用方法

我有一个泛型函数,它将函数包装在API中(我无法触及).包装函数采用System.Enum并返回相同的函数.我的通用版本在本示例的非剥离版本中简化了相当多的内容.

问题是,我无法从T到System.Enum,或者再次回到原因,因为T不限于System.Enum(至少这是我的理解).

以下代码有效,但我很想知道是否有任何隐藏的陷阱或更好的方法,因为我对泛型非常新:

using System
using System.Collections.Generic
...

    public T EnumWrapper<T>(T enumVar) where T : struct, IFormattable, IConvertible, IComparable
    {
        if (!typeof(T).IsEnum)
            throw new ArgumentException("Generic Type must be a System.Enum")

        // Use string parsing to get to an Enum and back out again
        Enum e = (Enum)Enum.Parse(typeof(T), enumVar.ToString());
        e = WrappedFunction(e);
        return (T)Enum.Parse(typeof(T), e.ToString());
    }
Run Code Online (Sandbox Code Playgroud)

如果这样可以,那就以此为例.我找不到这个,至少它是一个可行的解决方案.

在这种情况下,PS性能不是问题.我以为我认为字符串工作可能很慢而且我总是对性能提示感兴趣.

Mic*_*l B 5

您可以使约束更严格.所有枚举都实现了可跟随的接口IFormattable,IConvertible并且IComparable.这将极大地限制你的原语和枚举以及类似它们的类.

或者,如果您确实要创建仅可绑定到枚举的方法或类,则可以执行以下操作:

    public abstract class InvokerHelper<T> where T : class
    {
        public abstract R Invoke<R>(R value) where R : struct,T;
    }


        public class EnumInvoker : InvokerHelper<Enum>
        {
            public override R Invoke<R>(R value)
            {
                return (R)WrappedMethod(value);
            }
        }
Run Code Online (Sandbox Code Playgroud)

它很笨重,不能用于扩展方法,但你可以使它成为一个单例对象,然后只有泛型方法.

或者,您可以编写代码,C++/CLI或者Reflection.Emit允许您创建可以具有约束的类where T:struct,Enum

实际上看起来你只是想把一个通用的T调用一个带有枚举的方法并将其作为T返回?

然后以下将工作.

public static T WrappedMethodInvoker<T>(T value) where T:struct,IComparable,IFormattable,IConvertible
{
    Enum e;
    if((e = value as Enum) == null) 
       throw new ArgumentException("value must be an Enum")
    object res = WrappedMethod(e);
    return (T)res;
}
Run Code Online (Sandbox Code Playgroud)

这有点容易.首先我们知道T是一个Enum,你可以使用as运算符来尝试转换为可空类型(引用类型或可空结构),这Enum当然是.从那里我们可以使用返回类型的协方差,WrappedMethod返回一个Enum,这意味着我们可以将它存储在一个对象中.最后,当你在泛型方法中有一个对象时,你在语法上允许将它强制转换为T.它可能会失败,但我们知道该方法返回一个相同类型的枚举.

有一些成本需要知道,你总是拳击和拆箱.包装方法是通用的吗?

我已经编辑了答案,以显示修改为示例案例的第一个技术.它非常简单和类型安全,但你必须有一个EnumInvoker来执行操作.不幸的是,两个答案应该执行相同的操作,因为如果其参数为Enum,则调用WrappedMethod将为box值.第一种方法的唯一优点是它是强类型的,但是据我所知,泛型虚方法是最慢的调用方法.因此,避免类型检查可能不值得更容易调用.