c# 8.0 switch 表达式返回类型和空值

Posted

技术标签:

【中文标题】c# 8.0 switch 表达式返回类型和空值【英文标题】:c# 8.0 switch expression return type and null value 【发布时间】:2020-03-14 08:26:46 【问题描述】:

我正在尝试了解 C# 8.0 开关表达式的工作原理,但有几个问题。

    为什么不能在默认情况下使用null 值?编译器抛出Cannot convert null to 'int' because it is a non-nullable value type 错误。 为什么它试图将 null 值转换为 int 而函数的返回类型是 'double?'?

这是我正在玩的函数:

public static double? SwitchFunction(int x) =>
    x switch
    
        1 => 1,
        _ => null
    ;

【问题讨论】:

尝试将切换结果转换为double?。所有switch 响应都不是double? 类型。 这类似于var x = condition ? 1 : null; 不起作用,因为编译器不够聪明,无法知道您想要int? 编译器从您返回 int 值 (1) 的第一种情况推断出“int”类型。该开关的结果只会被转换为双倍?从通话中返回。 var x = condition ? 1 : (double)null; 会起作用。 @JasonInVegas Cannot convert null to 'double' because it is a non-nullable value type 【参考方案1】:

在 switch 表达式中,所有可能的值必须(隐式转换为)相同类型。因为您的第一个案例是1 => 1,,并且您没有将整数文字转换为int 以外的类型,所以其余案例也将被假定为int。您需要将该 1 转换为 (double?) 以让编译器将其余情况也解释为 double?,这是一种可为空的类型 - 这将解决您的两个问题。

【讨论】:

【参考方案2】:

您遇到了条件表达式中经常遇到的问题。

// Compiler Error CS0173
// Type of conditional expression cannot be determined because 
// there is no implicit conversion between 'int' and '<null>'
//
// var d2 = i == 1 ? 1 : null; 

// This works
var d2 = i == 1 ? 1 : (double?) null;

要解决switch 表达式中的问题,您可以通过指定null 的类型来帮助编译器。

int i = 2;
var d = i switch

    1 => 1,
    _ => (double?)null
;

【讨论】:

【参考方案3】:

我遇到了同样的问题,导致出现不同的错误消息:“没有为 switch 表达式找到最佳类型”。

var isRequired = someIntValue switch
    
      0 => null,
      1 => false,
      2 => true,
      _ => throw new NotSupportedException(),
    ;

在阅读此处的答案之前,我无法理解此错误消息。编译器无法确定 isRequired 的类型应该是什么。我的意图是布尔?将代码更改为此会使错误消息消失:

var isRequired = someIntValue switch
    
      0 => (bool?)null,
      1 => false,
      2 => true,
      _ => throw new NotSupportedException(),
    ;

另一方面,我可以告诉编译器我想要什么:

bool? isRequired = someIntValue switch
    
      0 => null,
      1 => false,
      2 => true,
      _ => throw new NotSupportedException(),
    ;

我在 GitHub 上读到他们打算在未来的版本中解决这个问题。

【讨论】:

以上是关于c# 8.0 switch 表达式返回类型和空值的主要内容,如果未能解决你的问题,请参考以下文章

c#异常可空对象必须要有一个值怎么解决

新的 C# 8.0 开关表达式的运算符优先级是啥?

ES11(2020)可选链操作符和空值合并运算符

ES11(2020)可选链操作符和空值合并运算符

c# 8 switch 表达式:没有找到 switch 表达式的最佳类型

如何在 C# Rest API 中处理查询参数中的可选 ENUM - 无效和空值以及在 Swagger 中隐藏特定值