2015-09-15 75 views
2

我想寫一個接受枚舉的通用類。由於該類旨在實現一些接口,主要目標是能夠將枚舉視爲實現這些接口的其他對象(例如用於列表擴展等)。因此,對於樣品枚舉枚舉的通用類 - 投射問題

public enum QEnum : int 
{ 
    xlNoValue = 0, 
    xlSomeValue = 1 
} 

public static class QEnumExtensions 
{ 
    public static string toString(this QEnum xThis) 
    { 
     ... 
    } 

    public static QEnum toEnum(this string xThis) 
    { 
     ... 
    } 
} 

我想聲明泛型類如

public class QEnumHolder<T> where T : struct, IConvertible 
{ 
    private T mxVal = default(T); 

    public QEnumHolder() 
    { 
     if (!typeof(T).IsEnum) throw new NotSupportedException(); 
    } 

    public QEnumHolder(T xVal) 
    { 
     if (!typeof(T).IsEnum) throw new NotSupportedException(); 
     mxVal = xVal; 
    } 

    static public implicit operator QEnumHolder<T>(T xVal) 
    { 
     return new QEnumHolder<T>(xVal); 
    } 

    static public implicit operator T(QEnumHolder<T> xVal) 
    { 
     return (T)xVal.mxVal; 
    } 

    public string toString() 
    { 
     if (mxVal is QEnum) return ((QEnum)Convert.ToInt32(mxVal)).toString();  
     ... 
    } 

    public void fromString(string xString) 
    { 
     if (mxVal is QEnum) 
      mxVal = (???)xString.toEnum();  // problem 
    } 
} 

所有我們使用實現

  • 的toString()函數返回的枚舉一個「漂亮」的字符串,可以進入comboBoxes等
  • 將字符串轉換爲枚舉,如上

因此toString/toEnum的結構幾乎是給定的。問題是最後一行代碼行標有「問題」。我不知道如何告訴編譯器,在這個分支中,toEnum()T的返回類型將是相同的。

我試圖通過宣佈mxValint並在任何地方使用Convert.ToInt32來解決此問題。然而,然後我碰到operator T問題,其中編譯器反對將int轉換爲T(編譯器無法知道T將枚舉,因此我不能使用任何「int to enum conversion」討論在這裏)。

+0

作爲一般規則,C#使用駱駝案例d代表'ToString()'你應該重寫。 – Bauss

+0

@Bauss:我知道,我只是不喜歡它。與Equals()等相同 - 如果你不覆蓋它,你會得到一個你不關心的實現,並且沒有人會通知你。 –

+0

這個設計有很多問題。如果你的類包含像'QEnum'和'(QEnum)something''這樣的代碼,即** ** concrete **類型,那麼它不是**泛型類。另外,你不能有一個只有返回類型不同的多個'ToEnum(string)'擴展方法。 –

回答

1

更好的設計是使用一些命名約定,把你所有的枚舉擴展方法在同一個靜態類,並結合您的支持類靜態構造函數中這些功能。事情是這樣的:

public static partial class MyEnumExtensions 
{ 
    public static MyEnumHolder<T> ToHolder<T>(this T source) 
     where T : struct, IConvertible 
    { 
     return new MyEnumHolder<T>(source); 
    } 
} 

public class MyEnumHolder<T> where T : struct, IConvertible 
{ 
    static readonly Func<T, string> toStringFunc; 
    static readonly Func<string, T> toEnumFunc; 
    static MyEnumHolder() 
    { 
     if (!typeof(T).IsEnum) throw new NotSupportedException(); 
     // Use your naming conventions 
     var name = typeof(T).Name; 
     toStringFunc = (Func<T, string>)Delegate.CreateDelegate(typeof(Func<T, string>), 
      typeof(MyEnumExtensions).GetMethod("toString", new[] { typeof(T) })); 
     toEnumFunc = (Func<string, T>)Delegate.CreateDelegate(typeof(Func<string, T>), 
      typeof(MyEnumExtensions).GetMethod("to" + name, new[] { typeof(string) })); 
    } 

    private T value; 
    public MyEnumHolder() { value = default(T); } 
    public MyEnumHolder(T value) { this.value = value; } 
    static public implicit operator MyEnumHolder<T>(T x) { return new MyEnumHolder<T>(x); } 
    static public implicit operator T(MyEnumHolder<T> x) { return x.value; } 
    public string toString() 
    { 
     return toStringFunc(value); 
    } 
    public void fromString(string xString) 
    { 
     value = toEnumFunc(xString); 
    } 
} 

樣品枚舉定義(可以是單獨的文件,但必須是在同一個項目裏):

public enum MyEnumA { A1, A2, A3 } 
partial class MyEnumExtensions 
{ 
    public static string toString(this MyEnumA x) 
    { 
     //... 
     return x.ToString(); 
    } 
    public static MyEnumA toMyEnumA(this string x) 
    { 
     //... 
     return (MyEnumA)Enum.Parse(typeof(MyEnumA), x); 
    } 
} 

public enum MyEnumB { B1, B2, B3 } 
partial class MyEnumExtensions 
{ 
    public static string toString(this MyEnumB x) 
    { 
     //... 
     return x.ToString(); 
    } 
    public static MyEnumB toMyEnumB(this string x) 
    { 
     //... 
     return (MyEnumB)Enum.Parse(typeof(MyEnumB), x); 
    } 
} 

測試:

var a = MyEnumA.A1.ToHolder(); 
var sA = a.toString(); 
a.fromString("A2"); 
var b = MyEnumB.B2.ToHolder(); 
var sB = b.toString(); 
b.fromString("B1"); 
+0

伊萬,非常感謝你,你的代碼比我的代碼更優雅。 –

1
mxVal = (T)(object)xString.toEnum(); 
+0

就像我說的那樣。「如果解決方案是微不足道的」。似乎工作,我會等待一個小時進行潛在的討論,然後接受。非常感謝。 –

+0

很高興幫助!我在處理泛型時遇到過這個問題 - 花了一些時間弄清楚它 –