编写具有多种类型的通用扩展方法时的类型推断问题

我正在为IEnumerable编写一个通用扩展方法,用于将对象列表映射到另一个映射对象列表。 这就是我希望该方法工作的方式:

IList
articles = GetArticles(); return articles.Map(_mappingEngine);

这是方法:

 public static IEnumerable Map(this IEnumerable list, IMappingEngine engine) { return list.Select(engine.Map); } 

但是articles.Map(_mappingEngine); 给出编译错误。 问题是T1的类型推断不起作用。 我必须明确地这样称呼它:

 articles.Map
(_mappingEngine);

如果我创建一个只有一个参数T1的扩展方法,如下所示:

 public static IEnumerable DummyMap(this IEnumerable list, IMappingEngine engine) { return list; } 

然后我可以像这样调用它,而不必指定T1:

 articles.DummyMap(_mappingEngine); 

有没有理由说编译器无法在Map的扩展方法中推断出T1的类型?

问题是T1的类型推断不起作用

实际上,问题不在于T1 – 它是T2; 此推断中不使用返回类型。 所以你不能这样做。 一个选项可能是流畅的API,例如:

 return articles.Map(_mappingEngine).To(); 

有类似的东西:

 public static MapProjection Map(this IEnumerable list, IMappingEngine engine) { return new MapProjection(list, engine); } public class MapProjection { private readonly IEnumerable list; private readonly IMappingEngine engine; internal MapProjection( IEnumerable list, IMappingEngine engine) {this.list = list; this.engine = engine;} public IEnumerable To() { return list.Select(engine.Map()); } } 

假设接口是这样的:

 public interface IMappingEngine { Func Map(); } 

我相信即使你提供T2而不提供T1,你也希望C#编译器推断出T1的类型。

关键是你可以使用类型推断,或者只是不使用它。 你不能混合两个世界:

  public void M(T t, S s) { } M("hello", "world!") 

此代码无法编译,但是:

  public void M(T t, S s) { } M("hello", "world!") 

..compiles。