内联 if 和接口(多态性)
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();
public class Foo : IFooBarable {...}
public class Bar : IFooBarable {...}
So why then will this not compile...
int a = 1;
IFooBarable ting = a == 1 ? new Foo() : new Bar();
but this will...
IFooBarable ting = a == 1 ? new Foo() : new Foo();
IFooBarable ting = a == 1 ? new Bar() : new Bar();
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
编译器首先尝试计算右侧表达式:
这两者之间没有隐式转换,因此会出现错误消息。你可以这样做:
The compiler first tries to evaluate the right-hand expression:
There's no implicit conversion between those two hence the error message. You can do this:
C# 语言规范的第 7.13 节对此进行了介绍。本质上,造成这种情况的原因是三元操作数的两个值的类型之间必须存在隐式转换。这种转换被认为是在变量类型不存在的情况下进行的。
因此
Foo
必须可转换为Bar
,反之亦然。也不是这样,会发生编译错误。后两者可以工作,因为它们只考虑 1 种类型(
Foo
或Bar
)。因为它们属于同一类型,所以确定表达式的类型很简单并且工作正常。This is covered in section 7.13 of the C# language spec. Essentially what's killing this scenario is that there must be an implicit conversion between the types of the 2 values for the ternary operands. This conversion is considered in the abscence of the type of the variable.
So either
Foo
must be convertible toBar
or vice versa. Neither is so a compilation error occurs.The latter 2 work though because they only consider 1 type (either
Foo
orBar
). Because they are of the same type determining the type of the expression is simple and it works fine.只是对此处发布的正确答案添加一点:有两个设计指南导致了此规范。
第一个是我们从“内到外”推理。当你说
我们首先计算x的类型,然后计算2的类型,然后计算y的类型,然后计算(2+y)的类型,最后计算x和(2+y)是否兼容类型。但我们不使用 x 的类型来决定 2、y 或 2+y 的类型。
这是一个很好的规则的原因是因为“接收者”的类型通常正是我们想要解决的问题:
我们在这里要做什么?我们必须计算出条件表达式的类型才能进行重载决策,从而确定它是指向 Foo 还是 Bar。因此,我们不能使用这样的事实:在我们分析条件表达式的类型时,比如说,去 Foo !这是一个先有鸡还是先有蛋的问题。
此规则的例外是 lambda 表达式,它从上下文中获取类型。使该功能正常工作非常复杂;请参阅我的 如果您有兴趣,请参阅有关 lambda 表达式与匿名方法的博客系列。
第二个要素是我们从不为您“魔法”出一种类型。当给定一堆我们必须从中推断出类型的东西时,我们总是推断出实际上就在我们面前的类型。
在您的示例中,分析是这样的:
为了与第一点保持一致,我们不会从外到内进行推理;我们不使用我们知道变量类型的事实来计算表达式的类型。但现在有趣的是,当我们
说“条件表达式的类型是集合{Cat,Dog}中的最佳类型”时。我们并不是说“条件表达式的类型是与 Cat 和 Dog 兼容的最佳类型”。那是哺乳动物,但我们不这样做。相反,我们说“结果必须是我们实际看到的”,而在这两个选择中,没有一个是明显的赢家。如果你说,
那么我们可以在“动物”和“狗”之间做出选择,而“动物”显然是赢家。
现在,请注意,在进行此类型分析时,我们实际上没有正确实现 C# 规范!有关错误的详细信息,请参阅我的
Just to add a bit to the correct answers posted here: there are two design guidelines that lead to this specification.
The first is that we reason from "inside to outside". When you say
we first work out the type of x, then the type of 2, then the type of y, then the type of (2+y), and finally, we work out whether x and (2+y) have compatible types. But we do NOT use the type of x in deciding what the type of 2, y or 2+y is.
The reason this is a good rule is because often the type of the "receiver" is exactly what we're trying to work out:
What are we to do here? We have to work out the type of the conditional expression in order to do overload resolution, in order to determine whether this is going to Foo or Bar. Therefore, we cannot use the fact that this is, say, going to Foo in our analysis of the type of the conditional expression! That's a chicken-and-egg problem.
The exception to this rule is lambda expressions, which do take their type from their context. Making that feature work properly was insanely complicated; see my blog series on lambda expressions vs anonymous methods if you're interested.
The second element is that we never "magic up" a type for you. When given a bunch of things from which we must deduce a type, we always deduce a type that was actually right in front of us.
In your example, the analysis goes like this:
In keeping with the first point, we do not reason outside-to-inside; we don't use the fact that we know the type of the variable we're going to in order to work out the type of the expression. But the interesting thing now is that when you have
we say "the type of the conditional expression is the best type in the set {Cat, Dog}". We do NOT say "the type of the conditional expression is the best type compatible with both Cat and Dog". That would be Mammal, but we don't do that. Instead, we say "the result has to be something we actually saw", and of those two choices, neither is the clear winner. If you said
then we have a choice between Animal and Dog, and Animal is the clear winner.
Now, note that we actually do not correctly implement the C# spec when doing this type analysis! For details of the error, see my article on it.
因为条件表达式的类型始终是从其两个部分推断的,而不是从要应用结果的变量推断的。仅当类型相等或一个类型与另一个类型引用兼容时,此推论才有效。在这种情况下,这两种类型都不与另一种类型引用兼容。
Because the type of the conditional expression is always inferred from its two parts, not from the variable to which the result is to be applied. This inference only works when the types are equal or one is reference compatible to the other. In this case, neither of the two types is reference compatible to the other one.