为什么泛型方法在通用方法不匹配时不能选择特定方法?

时间:2017-05-22 14:33:52

标签: c# generics

鉴于以下课程:

Point 3D-W : 
[0.003070864657310213;
0.0004761913292736786;
0.06461112415423849]

第二次调用Point 3D-W Normalized = [0.003070864657310213 / 0.06461112415423849; 0.0004761913292736786 / 0.06461112415423849; 0.06461112415423849 / 0.06461112415423849] 时出现编译错误,抱怨没有从Point 3D-W Normalized = [0.047528420183179314; 0.007370113668614144; 1.0] 转换为public static class MWE { public static void Foo<T, TColl>(Expression<Func<IFoo, bool>> bar, TColl foos) where TColl : IEnumerable<T> { } public static void Foo<T, TColl>(Expression<Func<IFoo, T>> bar, TColl foos) where TColl : IEnumerable<T> { } static MWE() { Foo(bar => bar.GetThing(), new List<IThing>()); Foo(bar => bar.GetBool(), new List<IThing>()); } } public interface IFoo { IThing GetThing(); bool GetBool(); } 。在我看来,编译器没有看到第一个重载,虽然它匹配(而第二个没有)。

为什么呢?有两种方法可以共存和工作吗?

3 个答案:

答案 0 :(得分:2)

无法调用第一个重载,因为没有足够的信息来推断泛型参数。您使用一个的通用参数TColl,但您从不在签名中使用T,因此无法推断它。

如果您明确指定了泛型参数,那么将选择第一个重载并且它将正常工作。

如果您只是完全删除第二个泛型参数,并在签名中使用IEnumerable<T>而不是TColl,则会简化这些方法,并允许两个现有调用正常运行。

答案 1 :(得分:2)

通用类型约束(where ...)不用于泛型类型推断(当您没有明确说明它们时推断TTCall)。您可能认为第一次重载中的T类型可能会被推断为IThing,因为您将List<IThing>作为TColl传递,但由于上述情况,情况并非如此。

由于无法推断泛型类型 - 此方法不参与重载解析,因此使用第二种方法。失败了,你看到了编译错误。

答案 2 :(得分:0)

首先看一下这个:

public static void Foo<T, TColl>(Expression<Func<IFoo, T>> bar, TColl foos)
    where TColl : IEnumerable<T>

编译器如何确定T是什么?它会查看您传递的表达式(bar)并查看返回类型。从那以后,它可以推断Tbar会返回IThing,因此TIThingTCollIEnumerable<IThing>

现在看看这个:

public static void Foo<T, TColl>(Expression<Func<IFoo, bool>> bar, TColl foos)
    where TColl : IEnumerable<T>

T是什么?它不是bar返回的类型,它被硬编码为bool。那是什么?编译器无法分辨,因此您可以使用此函数的唯一方法是显式地告诉它通用参数是什么:

Foo<IThing,List<IThing>>(bar => bar.GetBool(), new List<IThing>());

^这将编译。

无法弄清楚T是什么,它必须使用第一个函数,推断Tbool然后它会抱怨因为你传递了IEnumerable<IThing> IEnumerable<bool> 1}}何时需要SELECT * FROM DUAL