.net - 带有 Enum 的通用 T 并将 T 转换为 Enum

标签 .net generics casting enums constraints

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

Create Generic method constraining T to an Enum

我有一个通用函数,它在 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());
    }

如果这没问题,那么就以此为例。我找不到这个,至少这是一个可行的解决方法。

附言在这种情况下,性能不是问题。以为我在想弦乐工作可能很慢,我总是对性能技巧感兴趣。

最佳答案

您可以使约束更严格。所有枚举都实现了以下接口(interface) IFormattable , IConvertibleIComparable .这将在很大程度上限制您使用类似于它们的原语、枚举和类。

或者,如果您真的想创建一个只能绑定(bind)到枚举的方法或类,您可以执行以下操作:

    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);
            }
        }

它笨重且不能用于扩展方法,但您可以将其设为单例对象,然后只有泛型方法。

或者,您可以在 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;
}

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

有一些成本要知道,因为您总是在装箱和拆箱。包装的方法是通用的吗?

我已经编辑了答案以显示针对您的示例案例修改的第一种技术。它非常简单且类型安全,但您总是必须有一个 EnumInvoker 来执行这些操作。
不幸的是,这两个答案的表现应该差不多,因为如果调用 WrappedMethod 的参数是 Enum,那么它会装箱值。第一种方法的唯一优点是它是强类型的,但据我所知,通用虚拟方法是调用最慢的方法。因此,避免类型检查可能不值得为更轻松的调用付出代价。

关于.net - 带有 Enum 的通用 T 并将 T 转换为 Enum,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7508455/

相关文章:

java - 我们是否允许在实例化期间使用通配符

c# - 一劳永逸地使用泛型实现工厂模式

在 C 中转换数字数据类型

php - 在 laravel 5.3 中使用带访问器的强制转换

c# - C# 将对象转换为二维数组

.net - Entity Framework 模型是否可以传递 SQL 脚本以针对数据库运行

c# - 将自定义对象添加到 JObject 时出错

java - 添加参数后覆盖具有泛型返回类型的方法失败

postgresql - 在 PostgreSQL 中将 smallint 转换为 boolean

c# - .NET SerialPort 在 115200 bps 时是否可靠?