C# 提供动态过载时的StackOverflowException
我有一长串方法重载C# 提供动态过载时的StackOverflowException,c#,dynamic,overloading,stack-overflow,C#,Dynamic,Overloading,Stack Overflow,我有一长串方法重载M(…),我想提供一个通用方法M(object),它将根据对象的类型调用正确的重载。就在我编写一个用于调用正确重载的大型if语句之前,我意识到C#4具有dynamic关键字。所以我写了这个: class X { public void M(int x) { Console.WriteLine("M(int)"); } public void M(long x) { Console.WriteLine("M(long)"); } //
M(…)
,我想提供一个通用方法M(object)
,它将根据对象的类型调用正确的重载。就在我编写一个用于调用正确重载的大型if语句之前,我意识到C#4具有dynamic
关键字。所以我写了这个:
class X
{
public void M(int x)
{ Console.WriteLine("M(int)"); }
public void M(long x)
{ Console.WriteLine("M(long)"); }
// ...20 more overloads of M() here...
// For if you have an object of an unknown type:
public void M(dynamic x)
{ M(x); }
}
当我正确使用它时,一切都很好。但是,当我提供错误类型的值时,动态重载解析(显然)递归到M(dynamic)
,然后重试,导致无限递归,最终导致StackOverflowException
X x = new X();
x.M((int)10); // "M(int)"
x.M((long)10); // "M(long)"
x.M((object)10); // "M(int)"
x.M((object)String.Empty); // StackOverflowException
当然,M(动态)
重载在技术上与M(对象)
相同,因此重载解析将一次又一次地拾取动态重载
如何防止这种情况发生?我意识到不应该提供
M(动态)
重载。为了获得相同的行为,让调用方动态调用该方法。像这样:
X x = new X();
x.M((int)10); // "M(int)"
x.M((long)10); // "M(long)"
x.M((dynamic)10); // "M(int)"
x.M((dynamic)String.Empty); // RuntimeBinderException
最简单的方法是将“要调用的公共方法”与“实现”分开,这样调用方就不需要做任何事情:
请注意,在C#4中引入了动态。您的意思是,对于每个
M(…)
方法,都有一个对应的私有MImpl(…)
方法,然后让DLR在MImpl
上执行重载解析,而不是M
?@Virtlink:No,您只有一个M方法,它可以动态地分派给任意数量的MImpl方法。静态类型重载比动态类型重载快得多,并且为用户提供了有用的提示,因此在大多数情况下,我只想使用静态类型。否则,我显然不会公开其他重载。@Virtlink:在这种情况下,您可以提供M
重载,它只委托给MImpl
重载。那肯定有用。。。但老实说,你的要求并不明确。(特别是当你把表现带进来的时候,当你的问题中没有提到的时候。)
public void M(dynamic x)
{
MImpl(x);
}
private void MImpl(int x)
{
Console.WriteLine("M(int)");
}
// etc
private void MImpl(object x)
{
// No more specific overloads matched. Throw some appropriate exception,
// or take a default action.
}