C# · 12月 25, 2021

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

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

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

我的问题是,为什么不能呢? TextSectionDTO和ImageSectionDTO都是从SectionDTO派生的.我正在尝试创建一个章节列表,TextSection和ImageSection都是从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;}

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

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

注意:

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

解决方法 case Enums.SectionTypes.OnlyText: return new TextSection((TextSectionDTO) s);case Enums.SectionTypes.OnlyImage: return new ImageSection((ImageSectionDTO) s);

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

case Enums.SectionTypes.OnlyText: return (SectionDTO) new TextSection((TextSectionDTO) s);case Enums.SectionTypes.OnlyImage: return (SectionDTO) new ImageSection((ImageSectionDTO) s);

为什么这不是在编译器上实现的?我假设这是因为编译器必须检查许多不同的类型.假设您的两种类型Foo1和Foo2不直接派生自Bar,而是来自两个不同的(Bar1和Bar2),它们自己从Bar继承.现在编译器应检查Foo1和Foo2是否可以分配给它们不能的任何公共基类,并检查它们是否来自具有公共基类(Bar)的东西.最后,我们必须检查整个继承链直到对象,而不是提及任何应该检查的接口.

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