条件运算符令人困惑,但为什么呢?假设有两个类,都是同一个超类的后代,如下所示:classMySuperClass{}classA:MySuperClass{}classB:MySuperClass{}那么这个赋值不会通过编译器:新A():新B();编译器抱怨A和B不兼容(无法确定条件表达式的类型,因为“A”和“B”之间没有隐式转换[CS0173])。但它们都是MySuperClass类型,所以在我看来这应该可行。没什么大不了的;只需要一个简单的转换来启发编译器。但这肯定是C#编译器的障碍吗?你不同意吗?条件的结果应该是相同的类型。他们不是。来自MSDN,(?:operator):first_expression和second_expression的类型必须相同,或者必须存在从一种类型到另一种类型的隐式转换。由于A和B不是同一类型,并且您似乎没有定义隐式转换,因此编译器会抱怨。查看此博客,了解一些有趣的文章,了解C#编译器为什么做/不做“显而易见”的事情。此博客由EricLippert撰写,他是C#编译器的开发人员之一。请参阅语言规范的第7.14节?:运算符的第二个和第三个操作数x和y控制条件表达式的类型。·如果x是X类型,则y是Y类型。o如果存在从X到Y的隐式转换(§6.1),但不存在从Y到X的隐式转换,则Y是条件表达式的类型。o如果存在从Y到X的隐式转换(§6.1),但不存在从X到Y的隐式转换,则X是条件表达式的类型。o否则,无法确定表达式类型,并发生编译时错误。·如果只有x和y之一有类型,并且x和y都可以隐式转换为该类型,则这是条件表达式的类型。?否则,无法确定表达式类型,并发生编译时错误。本质上,操作数必须可以相互转换,但不能转换为其他类型。这就是为什么您需要在示例中或在可空值(int?foo=isBar?42:(int?)null)之类的情况下进行显式转换。声明类型不会影响评估,编译器必须从表达式本身中找出它。编译器不会试图找到一个共同的祖先,所以你需要一个显式的转换来显示你想把哪些祖先当作祖先;在你的情况下:MySuperClassp=myCondition?(MySuperClass)(newA()):(MySuperClass)(newB());这意味着条件运算符的两边返回相同的类型,这满足了编译器的要求。条件运算符(与任何其他运算符一样)必须定义其表达式表示的类型。对于条件运算符,它有两个步骤:操作数是否相同?如果是这样,那就是表达式的类型。是否存在从一种操作数类型到另一种操作数类型的隐式转换(但不是双向)?如果是这样,那么“其他”就是表达式的类型。没有祖先搜索,因为实现可能会导致您作为开发人员可以在该表达式中指定的歧义滑坡。一切都应该导致对象?这些值类型是隐式装箱的吗?界面呢?如果两种类型之间有多个公共接口,应该选择哪一种?在您的情况下,正如您发现的那样,您需要将其中一个操作数向上转换为父类型。一旦你这样做,规则2.)就得到满足(总是有从更具体的类型到更不具体的类型的隐式转换)。请注意,您只需将转换应用于其中一个操作数,而不是两个。罗兰·肖(RowlandShaw)对此做了很好的总结,但要了解为什么未隐式使用共同祖先,请考虑如果两个类都实现特定接口会发生什么情况。编译器将无法确定条件运算符使用哪种类型,因此将被迫使用对象。以上就是C#学习教程:条件运算符会搞混,为什么呢?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
