2014-10-02 76 views
2

我一个枚举,延伸短:为什么不能使用这种通用方法调用?

public enum EnumType : short 
{ 
    Value1 = 1, 
    Value2 = 2 
} 

然后,我有一个看起来像这样的实用方法:

public static class EnumUtilities 
{ 
    public static IEnumerable<Tuple<TEnum, TBase>> GetTuples<TEnum, TBase>() 
     where TEnum : struct, TBase 
    { 
     return GetValues<TEnum>().Select(x => new Tuple<TEnum, TBase>(x, x)); 
    } 

    public static IEnumerable<T> GetValues<T>() where T : struct 
    { 
     return Enum.GetValues(typeof(T)).Cast<T>(); 
    } 
} 

当我尝试调用它,我得到一个编译错误说的”类型EnumType必须可以转换为'short'才能在通用方法'IEnumerable> GetTuples()'中使用它作为参数'TEnum''

我无法理解EnumType如何不能转换为'当它被定义为分机时,“简短”结束'短'。我还没有理解如何以下编译,但上面的例子没有。任何帮助表示赞赏!

var enumType = EnumType.Value1; 
var value1 = (short)enumType; 
+0

'Enum'默认的类型是'int'的。所以隐式转换为“short”是不可能的。 – AgentFire 2014-10-02 18:21:23

回答

4

问题的原因是,在GetTuples<,>()泛型方法约束你写

TEnum: struct, TBase 

这意味着TEnum应从TBase派生型我想你想或多或少这样称呼它:。EnumUtilities.GetTuples<EnumType, short>()的事情是,在EnumType不是从short衍生

你的方式宣布它:

public enum EnumType: short 
{ ... } 

意味着只是short应该用于此枚举作为一个基本类型来表示其枚举成员。所有枚举类型都来自Enum类,因此调用GetTuples<EnumType, short>将不会使用您提供的代码进行编译,但将编译GetTuples<EnumType, Enum>

这就是为什么您的样品不能按照您的预期工作。

您可以通过删除继承的约束,并在运行时检查的基础类型修复GetTuples<,>()方法:

public static IEnumerable<Tuple<TEnum, TBase>> GetTuples<TEnum, TBase>() 
     where TEnum : struct, IConvertible 
{ 
    Type tEnumType = typeof(TEnum); 
    if (!tEnumType.IsEnum || Enum.GetUnderlyingType(tEnumType) != typeof(TBase)) 
    { 
     throw new ArgumentException("Invalid type specified."); 
    } 
    return GetValues<TEnum>().Select(x => new Tuple<TEnum, TBase>(x, (TBase)Convert.ChangeType(x, typeof(TBase)))); 
} 

现在你应该能够调用EnumUtilities.GetTuples<EnumType, short>();,它应该正确编译。

该解决方案的缺点是运行时检查效率低于使用编译时约束。

+1

这是理解的关键,当然:) “事情是,EnumType不是从短期派生的。” – 2014-10-08 14:35:35

0

您的EnumType继承自short,默认情况下是Enum,所以将EnumType的值强制转换为short,而使用它的效果很好。另一种方法是在初始化时将值转换为short,如下所示。

public enum EnumType : short 
{ 
    Value1 = (short)1, 
    Value2 = (short)2 
} 

在这种情况下,在使用它时不需要投射。

0

试试这个

public static class EnumUtilities 
{ 
    public static IEnumerable<Tuple<TEnum, object>> GetTuples<TEnum>() where TEnum : struct, IConvertible 
    { 
     if (!typeof(TEnum).IsEnum) 
      throw new Exception("wrong!"); 

     return GetValues<TEnum>().Select(x => new Tuple<TEnum, object>(x, Convert.ChangeType(x, x.GetTypeCode()))); 
    } 

    public static IEnumerable<T> GetValues<T>() where T : struct, IConvertible 
    { 
     if (!typeof(T).IsEnum) 
      throw new Exception("wrong!"); 

     return Enum.GetValues(typeof(T)).Cast<T>(); 
    } 
} 
相关问题