内联 if 和接口(多态性)

发布于 2024-08-18 17:15:20 字数 352 浏览 2 评论 0原文

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

挽手叙旧 2024-08-25 17:15:20

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

? new Foo() : new Bar();

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

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

The compiler first tries to evaluate the right-hand expression:

? new Foo() : new Bar();

There's no implicit conversion between those two hence the error message. You can do this:

IFooBarable ting = a == 1 ? (IFooBarable)(new Foo()) : (IFooBarable)(new Bar());
一曲爱恨情仇 2024-08-25 17:15:20

C# 语言规范的第 7.13 节对此进行了介绍。本质上,造成这种情况的原因是三元操作数的两个值的类型之间必须存在隐式转换。这种转换被认为是在变量类型不存在的情况下进行的。

因此 Foo 必须可转换为 Bar,反之亦然。也不是这样,会发生编译错误。

后两者可以工作,因为它们只考虑 1 种类型(FooBar)。因为它们属于同一类型,所以确定表达式的类型很简单并且工作正常。

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 to Bar or vice versa. Neither is so a compilation error occurs.

The latter 2 work though because they only consider 1 type (either Foo or Bar). Because they are of the same type determining the type of the expression is simple and it works fine.

自此以后,行同陌路 2024-08-25 17:15:20

只是对此处发布的正确答案添加一点:有两个设计指南导致了此规范。

第一个是我们从“内到外”推理。当你说

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。因此,我们不能使用这样的事实:在我们分析条件表达式的类型时,比如说,去 Foo !这是一个先有鸡还是先有蛋的问题。

此规则的例外是 lambda 表达式,它从上下文中获取类型。使该功能正常工作非常复杂;请参阅我的 如果您有兴趣,请参阅有关 lambda 表达式与匿名方法的博客系列

第二个要素是我们从不为您“魔法”出一种类型。当给定一堆我们必须从中推断出类型的东西时,我们总是推断出实际上就在我们面前的类型。

在您的示例中,分析是这样的:

  • 计算出结果的类型
  • 计算出替代方案的类型
  • 找到与结果和替代方案兼容的最佳类型
  • 确保存在从类型的转换条件表达式到使用条件表达式的事物的类型。

为了与第一点保持一致,我们不会从外到内进行推理;我们不使用我们知道变量类型的事实来计算表达式的类型。但现在有趣的是,当我们

b ? new Cat() : new Dog()

说“条件表达式的类型是集合{Cat,Dog}中的最佳类型”时。我们并不是说“条件表达式的类型是与 Cat 和 Dog 兼容的最佳类型”。那是哺乳动物,但我们不这样做。相反,我们说“结果必须是我们实际看到的”,而在这两个选择中,没有一个是明显的赢家。如果你说,

b ? (Animal) (new Cat()) : new 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

double x = 2 + y;

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:

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

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:

  • work out the type of the consequence
  • work out the type of the alternative
  • find the best type that is compatible with both the consequence and the alternative
  • make sure that there is a conversion from the type of the conditional expression to the type of the thing that is using the conditional expression.

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

b ? new Cat() : new Dog()

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

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

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.

香橙ぽ 2024-08-25 17:15:20

因为条件表达式的类型始终是从其两个部分推断的,而不是从要应用结果的变量推断的。仅当类型相等或一个类型与另一个类型引用兼容时,此推论才有效。在这种情况下,这两种类型都不与另一种类型引用兼容。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文