c# - 为什么 switch 表达式会从周围的上下文中推断出表达式类型,而其他类型不明确的表达式却不会?

标签 c# switch-statement

正如我在回答 this question ,我观察到 switch 表达式特有的一个非常奇怪的行为——当它们有一个不明确的类型时,它们似乎能够推断出它们的类型。
例如,这不会编译

double a = new Random().Next(2) == 0 ? (short)1 : (uint)1;
因为编译器“不看”double a部分类型检查时,看到表达式是类型 shortuint .表达式不能有两种类型,因此会输出错误。这可以。众所周知,C# 不会查看您分配给的变量类型,就像在泛型中一样:
static T F<T>() => default(T);
double d = F(); // can't infer that T is double
然而 , switch 表达式打破了这个“规则”。如果我用 switch 表达式重写第一个代码片段:
double a = (new Random().Next(2) == 0) switch {
    true => (short)1,
    false => (uint)1
};
然后突然编译!与第一个代码片段不同,编译器似乎注意到了 double a部分并发现我想要一个 double .我试着看 docs用于 switch 表达式,但它没有提到它将执行任何自动转换为结果类型或类似的东西。
为什么 C# 在处理 switch 表达式时如此聪明,而在处理其他类型的表达式(如三元运算符)时却不是?

最佳答案

来自 C# 语言 proposal用于 switch 表达式;

The type of the switch_expression is the best common type of the expressions appearing to the right of the => tokens of the switch_expression_arms if such a type exists and the expression in every arm of the switch expression can be implicitly converted to that type. In addition, we add a new switch expression conversion, which is a predefined implicit conversion from a switch expression to every type T for which there exists an implicit conversion from each arm's expression to T.


最常见的类型?

In some cases, a common type needs to be inferred for a set of expressions. In particular, the element types of implicitly typed arrays and the return types of anonymous functions with block bodies are found in this way.

Intuitively, given a set of expressions E1...Em this inference should be equivalent to calling a method

Tr M<X>(X x1 ... X xm)

with the Ei as arguments.

More precisely, the inference starts out with an unfixed type variable X. Output type inferences are then made from each Ei to X. Finally, X is fixed and, if successful, the resulting type S is the resulting best common type for the expressions. If no such S exists, the expressions have no best common type


由于这无法编译,因此会出现“没有最佳类型..”错误;
var x = (id == 0) switch
{
    true => (short)1,
    false => (uint)1
};
你的例子 double x ...约束输出类型,改变如何推断 switch 表达式的类型。但这只是我的猜测。
conditional operator有非常严格的规定;

The second and third operands, x and y, of the ?: operator control the type of the conditional expression.

  • If x has type X and y has type Y then
    • If an implicit conversion (Implicit conversions) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.
    • If an implicit conversion (Implicit conversions) exists from Y to X, but not from X to Y, then X is the type of the conditional expression.
    • Otherwise, no expression type can be determined, and a compile-time error occurs.
  • If only one of x and y has a type, and both x and y, of are implicitly convertible to that type, then that is the type of the conditional expression.
  • Otherwise, no expression type can be determined, and a compile-time error occurs.

TLDR;类型推断/提升规则非常不同。

关于c# - 为什么 switch 表达式会从周围的上下文中推断出表达式类型,而其他类型不明确的表达式却不会?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63257017/

相关文章:

c# - 使用枚举和 switch 语句 c#

c++ - 在案例中更改开关变量

c++ - 如果 C++ 枚举的 switch 语句中的枚举值 > const N,如何获取?

c# - 在重载方法中使用泛型

c# - 在 AppDomain 的设置和拆卸上创建包装器

c# - 元素 'id' 与嵌套类错误的任何字段或属性都不匹配

php - PHP 中的条件切换语句

c# - LINQ2SQL 选择订单并跳过/接受

c# - Razor动态表创建c#

c# - C# 中的 Case 语句 block 级声明空间