c# - 带有 Action<T> 参数重载的模糊方法调用

标签 c# ambiguity overload-resolution

使用不同的 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)
    {

    }    
}

调用 TestTestDecimal 的构造函数或 TestLong作为参数,我收到以下错误:

The call is ambiguous between the following methods or properties: 'Test(System.Action<long>)' and 'Test(System.Action<decimal>)'

我的猜测是在 long 之间进行了一些隐式转换和 decimal ,但是有没有人知道我做错了什么?有什么解决方法吗?

最佳答案

当你通过 TestDecimalTestLong作为参数,您实际上传递了一个方法组(毕竟,可能有不止一个 TestDecimal 方法 - 它可能已经过载)。因此在这两种情况下都会发生隐式转换 - 从方法组到特定的委托(delegate)类型。因此,这两种方法都是适用的候选者 ( Section 7.4.2 )。从适用的候选者中,重载解析算法试图找到最佳候选者。但是,匹配参数列表时比较转换的规则表明,如果两个候选者都发生隐式转换,则两者都不是更好:

Section 7.4.2.3 :

[...]

Otherwise, neither conversion is better.

这就是为什么您的情况存在歧义。


解决方法当然是首先显式转换参数:

new Test(new Action<decimal>(TestDecimal))

对于一种情况,这种方式在重载解析期间不需要隐式转换(因为转换后 Action<T> 类型将完全匹配),而另一种情况必须转换( Action<long>Action<decimal> ) ,并且上面提到的部分指出:

[...]

If S is T1, C1 is the better conversion.

If S is T2, C2 is the better conversion.

[...]

关于c# - 带有 Action<T> 参数重载的模糊方法调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24011887/

相关文章:

c# - 自动从azure函数获取结果

c# - 使用 MVVM 构建选项列表

c++ - 区分引用传递和值传递

c++ - "Manual"签名重载解析

c# - 独特的约束黑客 - Entity Framework

c# - 使用 LINQ 进行多数据查询

c#歧义错误

qt - 解决 QT 的 QString arg() 歧义

c++ - 非内置函数的模板,内置函数的重载

c++ - 涉及旧式枚举和整数类型的重载解析