【发布时间】:2016-06-16 09:47:27
【问题描述】:
我今天对方法解析的工作方式感到惊讶。
以代码为例:
class Program
{
static class Mapper<TSource, TTarget>
{
public static void Map<TMember>(Expression<Func<TSource, TMember>> source, Expression<Func<TTarget, TMember>> target)
{
Console.WriteLine("A");
}
public static void Map<TMember, TSourceCollection>(Expression<Func<TSource, TSourceCollection>> source, Expression<Func<TTarget, TMember[]>> target)
where TSourceCollection : IEnumerable<TMember>
{
Console.WriteLine("B");
}
}
class A
{
public byte[] prop { get; set; }
}
class B
{
public byte[] prop { get; set; }
}
static void Main(string[] args)
{
Mapper<A, B>.Map(x => x.prop, x => x.prop);
}
}
如您所见,方法 Map 有两种重载,一种是属性类型相同时,另一种是源属性是可枚举且正确的属性是数组。
然后当我调用两边都有数组的方法时,它调用第二个重载,但由于类型完全相同,我希望调用第一个重载。
我认为第一个重载的得分会更高,因为它依赖的泛型参数比第二个少,而且它更适合我传递给方法的参数类型。
有人能解释一下为什么编译器选择调用第二个重载而不是第一个吗?
谢谢。
【问题讨论】:
-
您使用 A 类和 B 类调用映射器,它们不是数组。它们都有一个字节数组的属性,但它们的类型不同。
-
将 byte[] 更改为 int 并使用第一个。所以我猜这是因为字节数组是一个 IEnumerable。
-
谢谢,但解决方案应该发生在 TMember,而不是 TSource 或 TTarget。 TSource 和 TTarget 本质上是不同的。
-
是的,字节数组和 IEnumerable 是兼容的。显然,两个重载都可以工作,但是当第一个说“如果两者都一样,带我走”时,为什么要选择第二个。在我的例子中,两者都是 byte[] 所以我希望第一个被选中...
标签: c# generics type-inference method-resolution-order