代码之家  ›  专栏  ›  技术社区  ›  gingerbreadboy

内联if和接口(多态性)

  •  1
  • gingerbreadboy  · 技术社区  · 16 年前
    public class Foo : IFooBarable {...}
    public class Bar : IFooBarable {...}
    

    那么为什么不编译这个呢?

    int a = 1;
    IFooBarable ting = a == 1 ? new Foo() : new Bar();
    

    但这会…

    IFooBarable ting = a == 1 ? new Foo() : new Foo();
    IFooBarable ting = a == 1 ? new Bar() : new Bar();
    
    4 回复  |  直到 16 年前
        1
  •  7
  •   BFree    16 年前

    编译器首先尝试计算右侧表达式:

    ? new Foo() : new Bar();
    

    这两者之间没有隐式转换,因此出现了错误消息。您可以这样做:

    IFooBarable ting = a == 1 ? (IFooBarable)(new Foo()) : (IFooBarable)(new Bar());
    
        2
  •  5
  •   JaredPar    16 年前

    这在C语言规范的第7.13节中有介绍。基本上,造成这种情况的致命原因是三元操作数的两个值的类型之间必须有隐式转换。在变量类型的横截面中考虑了这种转换。

    所以要么 Foo 必须可转换为 Bar 反之亦然。也不会发生编译错误。

    后两种方法是有效的,因为它们只考虑1种类型(或者 酒吧 )因为它们属于同一类型,所以确定表达式的类型很简单,而且工作正常。

        3
  •  4
  •   Eric Lippert    16 年前

    只需在这里的正确答案中添加一点:有两个设计指南可以引导这个规范。

    第一,我们从“内到外”进行推理。当你说

    double x = 2 + y;
    

    我们首先计算出x的类型,然后是2的类型,然后是y的类型,然后是(2+y)的类型,最后,我们计算出x和(2+y)是否有兼容的类型。但是我们不使用x的类型来决定2,y或2+y的类型。

    这是一条很好的规则,因为“接收者”的类型通常正是我们要解决的问题:

    void M(Foo f) {}
    void M(Bar b) {}
    ...
    M(x ? y : z);
    

    我们在这里做什么?为了进行重载解析,我们必须计算出条件表达式的类型,以便确定它是指向foo还是指向bar。因此,我们不能 使用 事实上,这就是,比方说,在我们分析条件表达式类型时要考虑的问题!这是鸡和蛋的问题。

    此规则的例外是lambda表达式,它 从上下文中提取他们的类型。使该功能正常工作是非常复杂的;请参阅我的 blog series 对lambda表达式和匿名方法感兴趣。

    第二个要素是我们永远不会为你“变魔术”一个类型。当我们给出一堆必须从中推导出一个类型的东西时,我们总是推导出一个实际上就在我们前面的类型。

    在您的示例中,分析过程如下:

    • 算出结果的类型
    • 确定备选方案的类型
    • 找到与结果和备选方案都兼容的最佳类型
    • 确保有一个从条件表达式类型到使用条件表达式的对象类型的转换。

    为了符合第一点,我们没有理由 从外到内 ;我们不使用这样一个事实,即我们知道要计算表达式类型的变量的类型。但现在有趣的是当你

    b ? new Cat() : new Dog()
    

    我们说“条件表达式的类型是集合中最好的类型cat,dog”。我们不说“条件表达式的类型是与cat和dog兼容的最佳类型”。那是哺乳动物,但我们不这么做。相反,我们说“结果必须是我们实际看到的东西”,在这两个选择中,没有一个是明确的赢家。如果你说

    b ? (Animal) (new Cat()) : new Dog()
    

    然后我们在动物和狗之间做出选择,动物显然是赢家。

    现在,请注意,在进行这种类型分析时,我们实际上没有正确地实现C规范!有关错误的详细信息,请参阅 article 关于它。

        4
  •  1
  •   Jeffrey L Whitledge    16 年前

    因为条件表达式的类型总是从它的两个部分推断出来的,而不是从要应用结果的变量推断出来的。只有当类型相同或其中一个引用与另一个引用兼容时,此推理才有效。在这种情况下,这两种类型都不与另一种类型兼容。

    推荐文章