我想编写一个接受枚举的泛型类。由于此类旨在实现某些接口,因此主要目的是能够将枚举视为实现这些接口的其他对象(例如,用于列表扩展等)。因此,对于样本枚举
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 / toEnum的结构。问题是最后一行标记为&#34;问题&#34;。我不知道如何告诉编译器在这个分支中,toEnum()
和T
的返回类型将是相同的。
我试图通过将mxVal
声明为int
并在任何地方使用Convert.ToInt32
来规避问题。但是,我在operator T
遇到了问题,编译器反对将int
转换为T
(编译器无法知道T
将是def put(self, request, format=None):
"""
This text is the description for this API.
---
parameters:
- name: username
description: Foobar long description goes here
required: true
type: string
paramType: form
- name: password
paramType: form
required: true
type: string
"""
username = request.DATA['username']
password = request.DATA['password']
枚举,因此我不能使用&#34; int来枚举转换&#34;讨论这里的SO)。
答案 0 :(得分:1)
mxVal = (T)(object)xString.toEnum();
答案 1 :(得分:1)
更好的设计是使用一些命名约定,将所有枚举扩展方法放在一个相同的静态类中,并将这些函数绑定在holder类 static 构造函数中。像这样:
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");