C# 内联if和接口(多态性)
那么,为什么这不会编译C# 内联if和接口(多态性),c#,.net-3.5,interface,inline-if,C#,.net 3.5,Interface,Inline 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 ? n
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();
这两者之间没有隐式转换,因此出现错误消息。您可以这样做:
? new Foo() : new Bar();
编译器首先尝试计算右侧表达式:
IFooBarable ting = a == 1 ? new Foo() : new Foo();
IFooBarable ting = a == 1 ? new Bar() : new Bar();
这两者之间没有隐式转换,因此出现错误消息。您可以这样做:
? new Foo() : new Bar();
C#语言规范第7.13节介绍了这一点。从本质上讲,扼杀这一场景的是三值操作数的2个值的类型之间必须存在隐式转换。在变量类型不存在时考虑此转换 因此,
Foo
必须可转换为Bar
,反之亦然。两者都不是,因此会发生编译错误
后面的2则是因为它们只考虑了1种类型(无论是代码> Foo还是<代码> BAR < /代码>。因为它们属于同一类型,所以确定表达式的类型很简单,而且工作正常。
这在C语言规范的第7.13节中有介绍。基本上,消除这种情况的原因是三元操作数的2个值的类型之间必须存在隐式转换。在变量类型不存在时考虑此转换 因此,Foo
必须可转换为Bar
,反之亦然。两者都不是,因此会发生编译错误
后面的2则是因为它们只考虑了1种类型(无论是代码> Foo还是<代码> BAR < /代码>。因为它们属于同一类型,所以确定表达式的类型很简单,而且工作正常。
因为条件表达式的类型总是从它的两个部分推断出来的,而不是从要应用结果的变量推断出来的。只有当类型相等或一个引用与另一个兼容时,此推断才有效。在这种情况下,这两种类型都与另一种类型的引用不兼容。因为条件表达式的类型总是从它的两个部分推断出来的,而不是从要应用结果的变量推断出来的。只有当类型相等或一个引用与另一个兼容时,此推断才有效。在这种情况下,这两种类型都与另一种类型不兼容。仅为此处发布的正确答案添加一点内容:有两种设计准则导致了本规范 首先,我们从“内部到外部”进行推理。当你说IFooBarable ting = a == 1 ? (IFooBarable)(new Foo()) : (IFooBarable)(new Bar());
我们首先计算x的类型,然后计算2的类型,然后计算y的类型,然后计算(2+y)的类型,最后计算x和(2+y)是否有兼容的类型。但是我们不使用x的类型来决定2,y或2+y的类型
这是一个好规则的原因是,通常“接收者”的类型正是我们试图解决的问题:
double x = 2 + y;
我们在这里干什么?为了进行重载解析,我们必须计算出条件表达式的类型,以便确定这是Foo还是Bar。因此,我们不能在分析条件表达式的类型时使用这一事实,比如说,使用Foo!这是鸡和蛋的问题
此规则的例外是lambda表达式,它确实从上下文中获取其类型。使这一功能正常工作是极其复杂的;如果您感兴趣,请参阅我的关于lambda表达式与匿名方法的文章
第二个要素是,我们从不为您“创造”一种类型。当我们从一堆东西中推断出一种类型时,我们总是推断出一种实际上就在我们面前的类型
在您的示例中,分析如下所示:
- 计算出后果的类型
- 计算出备选方案的类型
- 找到与结果和备选方案兼容的最佳类型
- 确保从条件表达式的类型转换为使用条件表达式的对象的类型
void M(Foo f) {}
void M(Bar b) {}
...
M(x ? y : z);
我们说“条件表达式的类型是集合{Cat,Dog}中的最佳类型”。我们并没有说“条件表达式的类型是与Cat和Dog兼容的最佳类型”。那可能是哺乳动物,但我们不这么做。相反,我们说“结果必须是我们实际看到的”,在这两个选择中,没有一个是明确的赢家。如果你说
b ? new Cat() : new Dog()
然后我们可以在动物和狗之间做出选择,动物显然是赢家
现在,请注意,在进行此类型分析时,我们实际上没有正确实现C#规范!有关错误的详细信息,请参阅my on it.仅为此处发布的正确答案添加一点内容:有两个设计准则导致了此规范 首先,我们从“内部到外部”进行推理。当你说
IFooBarable ting = a == 1 ? (IFooBarable)(new Foo()) : (IFooBarable)(new Bar());
我们首先计算x的类型,然后计算2的类型,然后计算y的类型,然后计算(2+y)的类型,最后计算x和(2+y)是否有兼容的类型。但是我们不使用x的类型来决定2,y或2+y的类型
这是一个好规则的原因是,通常“接收者”的类型正是我们试图解决的问题:
double x = 2 + y;
我们在这里干什么?为了进行重载解析,我们必须计算出条件表达式的类型,以便确定这是Foo还是Bar。因此,我们不能在分析条件表达式的类型时使用这一事实,比如说,使用Foo!这是鸡和蛋的问题
这个规则的例外是lambda表达式,它的类型来自t