我四处搜索,找不到任何这样做的例子,尽管这很有帮助:
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
, IConvertible
和 IComparable
.这将在很大程度上限制您使用类似于它们的原语、枚举和类。
或者,如果您真的想创建一个只能绑定(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/