我有一长串方法重载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(dynamic)
重载在技术上与M(object)
相同,因此重载决策会一次又一次地选择动态重载......
我该如何防止这种情况?
答案 0 :(得分:3)
执行此操作以使调用者不需要执行任何操作的最简单方法是将“要调用的公共方法”与“实现”分开:
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.
}
答案 1 :(得分:0)
我意识到M(dynamic)
重载应该不。要获得相同的行为,请让调用者动态调用该方法。像这样:
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