我有一个方法,通过用户传递一些输入值,传递一个Func委托,返回新值(非常简化为我想要实现的目标)
public L Coerce<L>(string value, Func<string, L> coercer)
{
return coercer(value);
}
Coerce<int>("123", v => int.Parse(v));
这很好但是我也希望能够编写覆盖特定类型行为的方法,例如......
public int Coerce<int>(string value)
{
return Coerce<int>(value, v => int.Parse(v));
}
所以基本上叫
Coerce<int>("123"); // equivalent Coerce<int>("123", v => int.Parse(v));
将节省我不得不为每个Coerce重写int.Parse。当然,这应该扩展到句柄
public decimal Coerce<decimal>(string value)
{
return Coerce<decimal>(value, v => int.Parse(v));
}
Etc等。
这可以整齐地完成吗?
詹姆斯
答案 0 :(得分:6)
好吧,如果你真的不想做
Convert.ToInt32(value)
然后这将按照你的要求行事:
public T Coerce<T>(string value) where T : IConvertible
{
return (T)(((IConvertible)value).ToType(typeof(T),
CultureInfo.InvariantCulture));
}
因此:
int x = Coerce<int>("123");
或
byte b = Coerce<byte>("123");
如果您尝试强制转换为不可转换类型,则会出现编译时错误,例如:
var x = Coerce<MyClass>("123"); //compile-time error
在这种情况下,您强制调用者使用Coerce(string value, Func<string,T> coercer)
重载。
答案 1 :(得分:1)
您可以使用非通用版本:
public int CoerceInt32(string value)
{
return Coerce(value, int.Parse);
}
答案 2 :(得分:0)
这种方法的目的是什么?
你为什么要写这个:
int x = Coerce<int>("123", v => int.Parse(v));
而不仅仅是这个:
int x = int.Parse("123");
然而,要回答你的问题,不,不要“整齐地”。 .Parse
是int和decimal类型的静态方法,因此无法通过泛型类型使用。
您可以期望的最好的方法是为每个要处理的类型编写一个重载,或者在方法中编写反射代码以确定要调用的静态方法。
因此,当你写这篇文章时会遇到问题:
MyMagicType x = Coerce<MyMagicType>("123");
那么呢?你会假设MyMagicType有一个.Parse方法吗?
答案 3 :(得分:0)
我担心C#不像C ++那样有模板覆盖。我遇到了类似的情况,我必须解决的方法是在运行时检查类型:
public void DoStuff<T>(Dictionary<object, T> arg) {
// ....
if (typeof(T) == typeof(ClassA)) {
DoStuff((Dictionary<object, ClassA>)arg);
}
else (typeof(T) == typeof(ClassB)) {
DoStuff((Dictionary<object, ClassB>)arg);
}
else {
throw new ArgumentException("T must be ClassA or ClassB");
}
}