【发布时间】:2015-09-15 16:17:42
【问题描述】:
我想编写一个接受枚举的泛型类。由于此类旨在实现某些接口,因此主要目的是能够将枚举视为实现这些接口的其他对象(例如,用于列表扩展等)。因此,对于一个示例枚举
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() 函数返回一个“漂亮”的字符串,可以进入组合框等
- 字符串到枚举的转换,如上
因此 toString/toEnum 的结构几乎是给定的。问题在于标记为“问题”的最后一行代码。我不知道如何告诉编译器,在这个分支中,toEnum() 和 T 的返回类型将是相同的。
我试图通过将mxVal 声明为int 并在任何地方使用Convert.ToInt32 来规避这个问题。但是,然后我在operator T 中遇到问题,其中编译器反对将int 转换为T(编译器不知道T 将是枚举,因此我不能使用任何一个关于 SO 的“int 到 enum 转换”讨论)。
【问题讨论】:
-
作为一般规则 C# 使用驼峰式大小写,对于
ToString()你应该覆盖。 -
@Bauss:我知道,我只是不喜欢它。 Equals() 等也是如此 - 如果你不覆盖它,你会得到一个你不关心的实现,并且没有人通知你。
-
这个设计有很多问题。如果您的类包含
is QEnum和(QEnum)something)之类的代码,即 具体 类型,那么它不是 泛型类。此外,您不能有多个ToEnum(string)扩展方法,它们仅在返回类型上有所不同。 -
@Ivan:是的,它不是泛型的,但是鉴于泛型不能仅限于枚举,你有更好的主意吗?至于第二点,枚举
QCountry会有toCountry(this string ..) -
缺少
enum约束是无关的。顺便说一句,您不必在每个构造函数中检查 - 只需创建一个 static 构造函数并将代码if (!typeof(T).IsEnum)...放在那里。问题是所有ifs 的需要。您是否真的打算为每个枚举编写所有这些扩展方法并还在您的持有者类toString和fromString方法中添加相应的if?