2015-09-15 76 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

很高兴帮助!我在处理泛型时遇到过这个问题 - 花了一些时间弄清楚它 –