2014-10-02 77 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>(); 
    } 
} 
相關問題