假设我有一个POCO和一个List类:
class MyClass
{...}
class MyClasses : List<MyClass>
{...}
以及以下将IEnumerable<MyClass>
映射到MyClasses
列表的方法:
public static TListType ToListOfType<TListType, TItemType>(this IEnumerable<TItemType> list) where TListType : IList<TItemType>, new()
{
var ret = new TListType();
foreach (var item in list)
{
ret.Add(item);
}
return ret;
}
我希望这段代码能够编译,但是不会:
var list = someListOfMyClass.ToListOfType<MyClasses>();
但是我得到
错误CS1061'IEnumerable'不包含以下定义 'ToListOfType',并且没有可访问的扩展方法'ToListOfType' 接受类型为“ IEnumerable”的第一个参数可能是 找到(您是否缺少using指令或程序集引用?)
但是,这确实可行:
var list = someListOfMyClass.ToListOfType<MyClasses, MyClass>();
我不明白为什么类型推断不足以使编译器知道项的类型,因为this
变量是已知类型的列表。
答案 0 :(得分:5)
类型推断不会从通用方法调用中推断 missing 参数。相反,它可以推断 all 或 none 个参数。因此,您不能使用一个类型参数来调用该方法,而期望编译器提供其余的参数。
在这种情况下,可以推断TItemType
,因为它在参数之一中。 TListType
不能被推断,因为它是返回类型。因此,最后无法推断出方法签名,而您必须指定所有类型参数。
答案 1 :(得分:2)
正如其他人所说,c#不支持部分泛型类型参数推断。
关于为什么不能推断出其中一种类型的原因,也许有一个更明显的例子更清楚了:
TPeeledFruit peeled = Peel<TPeeledFruit, TFruit)(
this TFruit fruit) where TPeeledFruit: TFruit
好的,现在你说:
var myPeeledBanana = Peel(myBanana)
编译器很容易推断出TFruit
必须为Banana
。
但是如何推断TPeeledFruit
是什么呢?它没有任何类型的信息。您可能会认为它很明显,因为您了解这种关系,但是编译器却没有这种知识。它唯一知道的是TPeeledFruit
必须是从TFruit
继承的类型,但可以是无限数量的类型:它可以再次为Banana
,可以是{{1} },可以是PeeledBanana
,PeeledRipeBanana
等
还要考虑这样一个事实,即明确地键入分配对任何情况都没有帮助:
PeeledGreenBanana
这也不起作用,因为c#会先在赋值的右侧键入类型,然后计算出赋值实际上是否合法。如果它是隐式类型的变量,则赋值始终有效。