C#方法调用中的委托引起歧义问题

6
在我的应用程序中,我有类似以下代码的内容:
class Program
    {
        static void Main(string[] args)
        {
            Method(uri => Task.FromResult(uri));
        }

        static void Method(Func<Uri, Uri> transformer)
        {
            throw new NotImplementedException();
        }

        static void Method(Func<Uri, Task<Uri>> transformer)
        {
            throw new NotImplementedException();
        }
    }

正如预期的那样,运行此代码将调用“Method”的第二个重载,即需要返回任务的函数委托。但是,如果我更改代码以避免在Main中使用匿名方法:

class Program
    {
        static void Main(string[] args)
        {
            Method(Method2);
        }

        static Task<Uri> Method2(Uri uri)
        {
            return Task.FromResult(uri);
        }

        static void Method(Func<Uri, Uri> transformer)
        {
            throw new NotImplementedException();
        }

        static void Method(Func<Uri, Task<Uri>> transformer)
        {
            throw new NotImplementedException();
        }
    }

C#编译器现在会报告我的对'Method'的调用是模棱两可的。我漏掉了什么吗?

1
你没有将Uri传递给Method2方法。 - Sam Axe
可能是因为Func<in T, out TResult>中的TResult是协变的。 - haim770
按照resharper的建议,强制转换为 Method((Func<Uri, Task<Uri>>) Method2); - M.kazem Akhgary
1
@M.kazemAkhgary,ReSharper建议解决歧义。问题是为什么会有歧义,因为从Func<Uri, Uri>Method2显然没有隐式转换。 - haim770
3
确实是重复问题,答案在这里:“这里的原则是,确定方法组可转换性需要使用重载解析从方法组中选择一个方法,并且重载解析不考虑返回类型。” - dcastro
显示剩余2条评论
1个回答

1
长的回答在https://dev59.com/AHI95IYBdhLWcg3w_zas#2058854(正如richzilla指出的)。
简短的回答是,C#编译器团队选择使方法组转换(例如Method(Method2))忽略返回类型(这里是Method2)。 这使他们在解析Expression树时具有灵活性。 不幸的是,这意味着编译器无法隐式选择您的2个Method签名之间的区别。
在进行lambda转换(Method(uri => Task.FromResult(uri)))时,编译器团队不需要担心表达式树解析,因此他们考虑返回类型。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接