在调用具有不同Action<T>
变体的重载方法时,我遇到了一些意外的编译器行为。
假设我有这个类Test
,我正在CallTest
构造函数中创建它的实例。
public class Test
{
public Test(Action<long> arg)
{
}
public Test(Action<decimal> arg)
{
}
}
public class CallTest
{
public CallTest()
{
Test t = new Test(TestDecimal);
}
public void TestDecimal(decimal arg)
{
}
public void TestLong(long arg)
{
}
}
使用Test
或TestDecimal
作为参数调用TestLong
构造函数时,我收到以下错误:
以下方法或属性之间的调用不明确:“
Test(System.Action<long>)
”和“Test(System.Action<decimal>)
”
我的猜测是在long
和decimal
之间进行了一些隐式转换,但有没有人知道我可能做错了什么?有没有解决方法?
答案 0 :(得分:6)
当您将TestDecimal
或TestLong
作为参数传递时,您实际上正在传递方法组(毕竟,可能会有多个{{} 1}}方法 - 它可能已被重载)。因此,在这两种情况下都会发生隐式转换 - 从方法组到特定的委托类型。因此,这两种方法都是适用的候选人(Section 7.4.2)。来自适用的候选者的重载决策算法试图找到最佳候选者。但是,在匹配参数列表状态时比较转换的规则,如果两个候选隐式转换都不发生更好:
[...]
否则,转换都不会更好。
这就是为什么在你的情况下存在歧义。
解决方法当然是首先明确地转换参数:
TestDecimal
对于一种情况,这种方式在重载解析期间不需要隐式转换(因为在转换new Test(new Action<decimal>(TestDecimal))
类型之后将完全匹配),而另一种情况则必须转换为Action<T>
Action<long>
),以及上面提到的部分说明:
[...]
如果S是T1,则C1是更好的转换。
如果S是T2,则C2是更好的转换。
[...]
答案 1 :(得分:1)
答案 2 :(得分:1)
有一种解决方法:
Test t = new Test(new Action<decimal>(TestDecimal));