可能重复:
没有使用泛型扩展方法进行类型推断
我有一个通用接口,以及它的两个具体实现。
然后我有一个方法,它是实现该接口的对象集合的扩展方法,它应该处理集合并返回处理后的集合。
处理操作不会更改对象也不会产生新对象,因此我希望该方法的输出与输入的类型相同。
换句话说,我不希望方法的输出是接口类型的集合,而是我传入的实际具体类型。
但是,这会导致调用方法时出现类型推断问题。
我将用一个LINQPad示例进行说明:
void Main()
{
var intervals = new Interval<int>[]
{
new Interval<int>(),
new Interval<int>(),
};
var ordered1 = intervals.Process(); // error 1
// var ordered2 = Extensions.Process(intervals); // error 2
}
public static class Extensions
{
public static IEnumerable<TInterval> Process<TInterval, T>(
this IEnumerable<TInterval> intervals)
where TInterval : IInterval<T>
{
return intervals;
}
}
public interface IInterval<T> { }
public class Interval<T> : IInterval<T> { }
这给了我以下两个编译时错误,您必须注释掉并在相关行中引发这两个消息:
错误 1:
“Interval<int>[]”不包含“Process”的定义,并且找不到接受“Interval<int>[]”类型的第一个参数的扩展方法“Process”(按 F4 添加使用指令或程序集引用)错误 2:
无法从用法中推断方法 'Extensions.Process<TInterval,T>(System.Collections.Generic.IEnumerable<TInterval>)' 的类型参数。尝试明确指定类型参数。
原因,或者我认为,是编译器在分析扩展方法是否适合时看起来“不够深入”。
如果我将扩展方法更改为:
public static IEnumerable<IInterval<T>> Process<T>(
this IEnumerable<IInterval<T>> intervals)
{
return intervals;
}
然后它编译,但因此输出是:
IEnumerable<IInterval<T>> result = ...
并不是:
IEnumerable<Interval<int>> result = ...
当然,如果我在调用的时候指定了类型,像这样:
var ordered = intervals.Process<IInterval<int>, int>();
...然后它可以工作,但这并不是那么好(IMO。)有没有办法欺骗编译器为我推断类型?
基本上,我想:
- 获取我调用方法的类型,而不是输入到接口的结果
- 避免一直告诉编译器是的,这确实是使用这些类型的另一个调用。这样做的原因是该方法将成为类似 LINQ 的调用链的一部分,因此我必须在每次调用后强制转换回已知类型,或者为每次调用指定完整类型。