![](/img/trans.png)
[英]Can't omit the extension type argument when calling generic extension method with mutually constrained type parameters
[英]missing extension method on constrained generic function
我的问题代码是这样的:
public void MyMethod<U, T>(U Array) where U : List<T>
{
var sum = Array.Sum();
}
我得到的编译时间错误是这样的:
错误CS1929'U'不包含'Sum'的定义,最佳扩展方法重载'Queryable.Sum(IQueryable)'需要类型为'IQueryable'的接收器
这是.NET Framework 4.6的Visual Studio 2015年这类似于这个问题在这里 ,但我不知道,如果同样的答案是有效的,因为编译器可以看到该方法被明确限制。
任何人都可以给我一些关于为什么我得到这个错误的指示吗?
编辑:
示例代码可以进一步简化:
public void MyMethod<T>(List<T> myList)
{
var sum = myList.Sum();
}
的重载Sum
不具有参数的非通用重载Sum
其中IEnumerable
已知是数字类型之一,例如:
public static int Sum(IEnumerable<int> source);
public static double Sum(IEnumerable<double> source);
//etc.
允许源序列为任何类型的泛型重载都需要一个选择器,该选择器将项目投影为数值。
为了增加Servy的出色答案,您可以将选择器传递给要在Sum
使用的方法,如下所示:
public void MyMethod<T, U>(U items, Func<T, int> selector) where U : List<T>
{
var sum = items.Sum(selector);
}
并这样称呼它:
MyMethod<int, List<int>>(l, i => i);
Servy的回答是,它必须是数字类型,但不是为什么,让我们检查一下。
给定以下功能模板:
public T SomeMethod<T>(List<T> items) where T : int { }
这是一个简单的操作,泛型被限制为特定类型,因此不需要泛型(用int
替换T
,并且其行为相同)。
现在,假设数字类型的类型系统具有一个称为“ NumericType”的通用基类:
public T SomeMethod<T>(List<T> items) where T : NumericType { }
看起来完全像您可能想要的,但是这里有个问题, 返回类型是什么? 假设列表包含double
, int
, byte
等,每个列表在与某些其他类型相乘,相加,除等后均具有加宽转换,因此编译器很难知道返回的类型。
如果允许我们做类似的事情,那将是同样的问题:
public T SomeMethod<T>(List<T> items) where T : in(int, double, float) { }
一个int
* int
== int
,但是int
* double
== double
,或更糟糕的是, double
/ int
== int
,正如您所看到的, T
不能被推断,这会破坏语言中的其他构造,例如:
var mySum = SomeMethod(myNumericList);
由于var
是在编译时隐式键入的,因此它无法确定适当的类型,因此无法编译该语句。
您可以做的最好的事情就是重载函数,这样您的原型就变成了:
public int SomeMethod(IEnumerable<int> items) { }
public double SomeMethod(IEnumerable<double> items) { }
public float SomeMethod(IEnumerable<float> items) { }
或者,另一方面,您可以坚持通用约束并执行以下操作:
public void MyMethod<U, T>(U items) where U : List<T>
{
if (typeof(T) is int) { ((List<int>)items).Sum() }
if (typeof(T) is double) { ((List<double>)items).Sum() }
//Repeat for the remaining numeric types.
}
或者,正如DavidG的答案所指出的,请使用选择器功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.