为什么编译器不能推断出这个select调用的类型?

Glu*_*bus 6 c# linq type-inference

我正在尝试通过调用DTO列表中的select来创建DTO中的ViewModel列表.但是,编译器给出了一个错误说:

无法从指定类型参数的用法尝试推断方法的类型参数

我的问题是,为什么不能呢?双方TextSectionDTOImageSectionDTO都源于SectionDTO.我试图创建ListSections,并且都TextSectionImageSection衍生自Section.

我知道这个问题与此处发布的其他一些问题很接近,但我无法在那里找到答案.

这是我的代码:

private List<Section> BuildSectionViewModel(IEnumerable<SectionDTO> ss )
{
    var viewModels = ss.Select((SectionDTO s) =>
    {
        switch (s.SectionType)
        {
            case Enums.SectionTypes.OnlyText:
                return new TextSection((TextSectionDTO) s);
            case Enums.SectionTypes.OnlyImage:
                return new ImageSection((ImageSectionDTO) s);
            default:
                throw new Exception("This section does not exist - FIXME");
        }
    }).ToList();

    return viewModels;
}
Run Code Online (Sandbox Code Playgroud)

当我更改类型以便我只接受超类SectionDTO并且只返回Section(我在这个场景中使它们都成为普通类)时,select会像你期望的那样工作.然后,当我将类型更改为TextSectionDTO和TextSection(更改摘要)时,select不再起作用.

我想要一个解决方案,这样我就可以使用我现在的构造工作,尽管我更感兴趣的是它为什么不能按原样运行.即使我可以让它工作,我也可能稍后重构.

注意:

  • 我的目标是MVC 4.5(所以编译器不是一些旧的版本无法推断,这是这里的一些类似问题的解决方案).
  • switch子句有一个默认情况,即错误不应该由不返回值的路径引起.

Him*_*ere 6

case Enums.SectionTypes.OnlyText:
    return new TextSection((TextSectionDTO) s);
case Enums.SectionTypes.OnlyImage:
    return new ImageSection((ImageSectionDTO) s);
Run Code Online (Sandbox Code Playgroud)

这两种情况返回不同的类型.编译器不够聪明,无法检查这些类型是否派生自相同的基类型,因此您必须明确地转换它们:

case Enums.SectionTypes.OnlyText:
    return (SectionDTO) new TextSection((TextSectionDTO) s);
case Enums.SectionTypes.OnlyImage:
    return (SectionDTO) new ImageSection((ImageSectionDTO) s);
Run Code Online (Sandbox Code Playgroud)

为什么这不是在编译器上实现的?我假设这是因为编译器必须检查许多不同的类型.假设你的两种类型Foo1,并Foo2没有直接获得Bar,但是从两个不同的人(Bar1Bar2相应的),其themselfs继承Bar.现在,编译器应该检查是否Foo1Foo2可分配到任何通用基础类,他们不能,并检查他们是否来自东西,有一个共同的基类派生的(Bar).最后,我们必须检查整个继承链,直到object没有提到任何应该检查的接口.

class Foo1 : Bar1 {}
class Foo2 : Bar2 {}

class Bar1 : Bar {}
class Bar2 : Bar {} 
Run Code Online (Sandbox Code Playgroud)