提供动态重载时的StackOverflowException

时间:2013-04-17 15:26:40

标签: 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)"); }

    // ...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)相同,因此重载决策会一次又一次地选择动态重载......

我该如何防止这种情况?

2 个答案:

答案 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