c# - 泛型、重载决议和委托(delegate)(抱歉,找不到更好的标题)

标签 c# generics compiler-construction overload-resolution

<分区>

Possible Duplicate:
Why is Func<T> ambiguous with Func<IEnumerable<T>>?

我注意到泛型有一个非常奇怪的重载解析问题...

考虑以下方法:

static void Foo<TSource>(TSource element, Func<TSource, int> selector)
{
    "int".Dump();
}

static void Foo<TSource>(TSource element, Func<TSource, double> selector)
{
    "double".Dump();
}

static T Identity<T>(T value)
{
    return value;
}

(C# 4,在 LINQPad 中测试)

如果我尝试调用 Foo使用 lambda 表达式作为选择器,一切正常:

Foo(42, x => x); // prints "int"

但是如果我替换 x => xIdentity , 编译器无法在 2 Foo 之间做出决定重载:

Foo(42, Identity);
// The call is ambiguous between the following methods or properties:
// 'UserQuery.Foo<int>(int, System.Func<int,int>)' and
// 'UserQuery.Foo<int>(int, System.Func<int,double>)'

第二个重载如何成为有效候选者?类型推断正确地确定了 TSourceint , 所以 T Identity 的参数方法必须是 int同样,所以返回类型必须是 int太... Identity可能是 Func<int,int>Func<double,double> , 但不是 Func<int,double> !

而且情况变得更糟!即使我明确指定了所有类型参数,我仍然会得到同样的错误:

Foo<int>(42, Identity<int>); // The call is ambiguous...

这里怎么会有歧义呢?据我所知,没有办法使用 Func<int,double> 的重载。可以是候选人。我猜解释一定在规范中的某处,但我找不到相关位...或者它可能是编译器中的错误,但我想这不太可能。

请注意,如果我显式创建委托(delegate),它确实有效:

Foo(42, new Func<int, int>(Identity)); // prints "int"

那么,有人可以解释一下这里发生了什么吗?另外,为什么它适用于 lambda 但不适用于方法组?

最佳答案

不就是因为返回类型不是方法签名的一部分吗?

事实是 Identity<T>在尝试决定 Foo<TSource> 的哪个重载时,编译器不会考虑方法的参数类型和返回类型保证相同。是必须的。如果不考虑返回类型,则 Identity<int>同样可以转换为 Func<int, int> , Func<int, double>Func<int, anything> .

关于c# - 泛型、重载决议和委托(delegate)(抱歉,找不到更好的标题),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4599730/

相关文章:

c - g-wan 不更新 servlet 的依赖项

c# - Asp.NET Core 自定义 Input Tag Helper 呈现重复的复选框

c# - 分页和页面冲突 - ASP.Net Core Razor 页面与 MVC Controller 方法分页冲突

javascript - 跨域 Javascript 访问 WCF 自托管服务时出现 404/405 错误

swift - 如何使用内部协议(protocol)的初始值设定项在公共(public)函数中构造新值?

c# - Windows 应用商店应用程序 AppContainerCheck 失败

c# - 在 C# 中按值传递引用类型

delphi - 为shortstring声明泛型内联函数const是用户错误,还是编译器错误?

java - Java 中的泛型用法是什么? X.<Y>方法()

scala - scala.util.parsing.ast.Binders 应该如何使用?