泛型隐藏式推理?

时间:2011-11-17 11:56:17

标签: c# generics type-inference nested-generics

  

可能重复:
  No type inference with generic extension method

我有一个通用接口,以及它的两个具体实现。

然后我有一个方法,它是实现该接口的对象集合的扩展方法,它应该处理集合并返回已处理的集合。

处理操作不会更改对象也不会生成新对象,因此我希望该方法的输出与输入的类型相同。

换句话说,我不希望方法的输出是接口类型的集合,而是我传入的实际具体类型。

但是,这会在调用方法时导致类型推断出现问题。

我将使用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&lt; int&gt; []'不包含'Process'的定义,也没有扩展方法'Process'可以找到'Interval&lt; int&gt; []'类型的第一个参数(按F4添加using指令或装配参考)

     

错误2:
  无法从用法推断出方法'Extensions.Process&lt; TInterval,T&gt;(System.Collections.Generic.IEnumerable&lt; TInterval&gt;)'的类型参数。尝试明确指定类型参数。

我认为原因是,在分析扩展方法是否合适时,编译器看起来并不“足够”。

如果我将扩展方法更改为:

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。)有没有办法欺骗编译器为我推断类型?

基本上,我想:

  1. 获取我用方法调用方法的类型,而不是将结果输入到接口
  2. 避免不断告诉编译器是,这确实是使用这些类型的另一个调用。原因是该方法将成为类似LINQ的调用链的一部分,因此我必须在每次调用后回转到已知类型,或者为每次调用指定完整类型。

0 个答案:

没有答案