C# 编写具有多个类型的泛型扩展方法时的类型推断问题

C# 编写具有多个类型的泛型扩展方法时的类型推断问题,c#,generics,c#-3.0,extension-methods,C#,Generics,C# 3.0,Extension Methods,我正在为IEnumerable编写一个通用扩展方法,用于将一个对象列表映射到另一个映射对象列表。这就是我希望该方法的工作方式: IList<Article> articles = GetArticles(); return articles.Map<ArticleViewModel>(_mappingEngine); 编译器无法在Map的扩展方法中推断T1的类型有什么原因吗 问题是T1的类型推断不起作用 事实上,问题不是T1,而是T2;此推断中未使用返回类型。所以你不能

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

IList<Article> articles = GetArticles();
return articles.Map<ArticleViewModel>(_mappingEngine);
编译器无法在Map的扩展方法中推断T1的类型有什么原因吗

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

事实上,问题不是T1,而是T2;此推断中未使用返回类型。所以你不能这么做。一个选项可能是fluent API,例如:

return articles.Map(_mappingEngine).To<SomeT2>();
returnarticles.Map(_-mappingEngine).To();
比如:

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

    public IEnumerable<T2> To<T2>()
    {
        return list.Select(engine.Map<T1, T2>());
    }
}
public interface IMappingEngine {
    Func<T1, T2> Map<T1, T2>();
}
公共静态地图投影地图(此IEnumerable列表,IMappingEngine引擎)
{
返回新的MapProjection(列表、引擎);
}
公共类地图投影
{
私有只读IEnumerable列表;
专用只读IMappingEngine引擎;
内部映射投影(IEnumerable列表、IMappingEngine引擎)
{this.list=list;this.engine=engine;}
公共IEnumerable To()
{
返回列表。选择(engine.Map());
}
}
假设接口类似于:

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

    public IEnumerable<T2> To<T2>()
    {
        return list.Select(engine.Map<T1, T2>());
    }
}
public interface IMappingEngine {
    Func<T1, T2> Map<T1, T2>();
}
公共接口IMappingEngine{
Func映射();
}
我相信您希望C#编译器推断T1的类型,即使您提供T2而不提供T1

关键是您可以使用类型推断,也可以不使用它。你不能把两个世界混在一起:

    public void M<T, S>(T t, S s)
    {
    }

    M<string>("hello", "world!")
public void M(T,S)
{
}
M(“你好”,“世界!”)
此代码不编译,但:

    public void M<T, S>(T t, S s)
    {
    }

    M("hello", "world!")
public void M(T,S)
{
}
M(“你好”,“世界!”)

…编译。

我希望它推断T1,而不是T2。T1是该方法所基于的类型(即我的示例中的IEnumerable)。它几乎相同。T1、T2或T1000(不,它不是终止符…)。你不能两者兼而有之。您可以使用类型推断,也可以避免使用类型推断:这是一个很好的解决方案,但是我仍然很好奇为什么这种推断在我的案例中不起作用。编译器不应该搜索所有匹配的泛型扩展方法吗?如果您指定泛型参数,它可以是all或nothing。这里有关于支持“咕哝”输入的讨论,例如
Map@Marc,我相信我已经回答了他。总之,“为什么?”这只是一个语言实现的细节,它不可能有一些很好的答案,可以有吗?啊,现在有道理了。我想它也会尝试评估Map,但我知道这会导致歧义。谢谢@Can-问题是:你可以有
Foo()
Foo()
Foo()
-需要特殊的逻辑来理解你的意思。
    public void M<T, S>(T t, S s)
    {
    }

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

    M("hello", "world!")