为什么编译器无法推断此选择调用的类型

本文关键字:选择 调用 类型 编译器 为什么 | 更新日期: 2023-09-27 18:33:08

>我正在尝试通过调用DTO列表中的选择来创建DTO的ViewModels列表。但是,编译器给了我一个错误,说:

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

我的问题是,为什么不能?TextSectionDTOImageSectionDTO都派生自SectionDTO。我正在尝试创建一个Sections ListTextSectionImageSection都派生自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 时(在这种情况下,我使它们都是普通类(,选择的工作方式就像您期望的那样。然后,当我将类型更改为仅文本部分DTO和文本部分(将摘要更改回来(时,选择不再起作用。

想要一个解决方案,以便我可以让它与我现在拥有的结构一起工作,尽管我更感兴趣的是为什么它不能按原样工作。即使我能让它工作,我以后也可能会重构它。

注意:

  • 我的目标是 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);

为什么这不在编译器上实现?我认为这是因为编译器必须检查许多不同的类型。假设您的两种类型的Foo1Foo2不是直接派生自Bar而是从两个不同的类型(相应地Bar1Bar2(派生,它们本身继承自Bar。现在编译器应该检查Foo1Foo2是否可以分配给它们不能分配给任何公共基类,并检查它们是否派生自具有公共基类(Bar(的东西。最后,我们不得不检查整个继承链,直到object,没有提到任何应该检查的接口。

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

Select方法有两种类型-TSourceTResult。由于你在IEnumerable<SectionDTO>上调用它,TSource被推断为SectionDTO,所以ss.Select((SectionDTO s) =>是不需要的,可以只是ss.Select(s => ...

问题是在您的情况下无法推断出TResult。为什么?您有两个回报 - TextSectionImageSection .它们不一样,它们都不是另一个的基础。你认为编译器应该推断什么?您认为答案应该是公共基类型Section,但同样适用于公共基object或两种类型的任何公共基类/接口。换句话说,结果是不明确的,因此编译器不会猜测您的意图,而是要求您显式指定。与三元运算符类似? :仅在一个分支中指定公共基数就足够了,因此以下内容应该可以解决它

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