我希望能够调用具有Nullable参数的泛型foo方法。当Foo方法的主体调用Foo()时,它会递归,导致堆栈溢出(没有.com)。有没有办法让if语句中的调用使用运行时类型调用正确的重载?
我知道更改名称会这样做,我理解为什么递归正在发生,但不知道另一种写这个的方法。
感谢您的光临。
class Program {
static void Main(string[] args) {
int? x = 5;
int y = 10;
Foo(x, y);
}
static void Foo<T>(Nullable<T> arg, T defaultValue) where T : struct {
if (arg.HasValue)
Foo(arg.Value, defaultValue);
}
static void Foo(int arg, int defaultValue) {
Console.WriteLine(string.Format("I'm an int arg={0}, default={1]}", arg, defaultValue));
}
static void Foo(string arg, int defaultValue) {
Console.WriteLine(string.Format("I'm an string arg={0}, default={1]}", arg, defaultValue));
}
static void Foo(bool arg, int defaultValue) {
Console.WriteLine(string.Format("I'm an double arg={0}, default={1]}", arg, defaultValue));
}
}
答案 0 :(得分:1)
泛型是一个编译时功能,在程序运行之前已经决定了重载决策。如果您想要强制执行运行时决策,您可以使用dynamic
来实现该目标(在C#4 +中)。除此之外,你只需要在int和bool之间转换为适用的类型。
if (arg.HasValue)
Foo((dynamic)arg.Value, defaultValue);
但要注意!这仅解决了int
和bool
的问题。其他类型可以传递给泛型方法,并且这些类型将继续解析为后续调用中的泛型方法。
Foo(5.0, 10.0); // would still overflow with your given methods
按照您的初步判断,如果您想支持int
,string
和bool
,只需拥有这些重载。如果要支持任何给定的T,请为T创建重载。
static void Foo<T>(T arg, T defaultValue)
{
Console.WriteLine(string.Format("I'm a T arg={0}, default={1}", arg, defaultValue));
}
如果根据编译时信息适用,则重载决策仍然会选择int
,bool
,string
或T?
重载。所有其他电话,和与arg.Value
的通话都将转到此新的重载。