我注意到泛型有一个非常奇怪的重载解决问题......
考虑以下方法:
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 => x
为Identity
,编译器将无法在两个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>)'
第二个重载如何成为有效的候选人?类型推断正确地确定TSource
是int
,所以方法的T
参数Identity
也必须是int
,所以返回类型也必须是int
......Identity
可以是 aFunc<int,int>
或 a Func<double,double>
,但不是 a Func<int,double>
!
而且情况会变得更糟!即使我明确指定所有类型参数,我仍然会收到相同的错误:
Foo<int>(42, Identity<int>); // The call is ambiguous...
这里怎么可能有歧义?据我所知,接受 a 的重载Func<int,double>
不可能成为候选者。我想解释必须在规范中的某个地方,但我找不到相关的位......或者它可能是编译器中的一个错误,但我想这不太可能。
请注意,如果我明确创建委托,它确实有效:
Foo(42, new Func<int, int>(Identity)); // prints "int"
那么,有人可以解释这里发生了什么吗?另外,为什么它适用于 lambda 而不是方法组?