【问题标题】:Can a swift switch be exhaustive for type Double without a default case?对于没有默认情况的 Double 类型,快速开关可以详尽无遗吗?
【发布时间】:2025-12-14 04:10:01
【问题描述】:

对于没有默认情况的 Double 类型,快速切换可以穷举吗?

这个开关(没有默认情况)给出错误:开关必须是详尽的:

    var minY = 1.0

    switch minY {
    case -(Double.infinity)..<0.9:
        yAxisMinimum = 0.0
    case (0.9..<0.99):
        yAxisMinimum = 0.9
    case (0.99..<0.999):
        yAxisMinimum = 0.99
    case (0.999..<0.9999):
        yAxisMinimum = 0.999
    case (0.9999...Double.infinity):
        yAxisMinimum = 0.9999
    }

但是这个开关,在(无用的)默认情况下,可以工作:

    var minY = 1.0

    switch minY {
    case -(Double.infinity)..<0.9:
        yAxisMinimum = 0.0
    case (0.9..<0.99):
        yAxisMinimum = 0.9
    case (0.99..<0.999):
        yAxisMinimum = 0.99
    case (0.999..<0.9999):
        yAxisMinimum = 0.999
    case (0.9999...Double.infinity):
        yAxisMinimum = 0.9999
    default:
        yAxisMinimum = 0.0
    }

我尽量避免使用我的开关的默认情况,但不知道是否可以使用 Double。

【问题讨论】:

  • 您的第一个switch 并未涵盖所有情况。您还需要处理NaNs。 (虽然我不知道这是否会修复编译器错误。)
  • 你也没有处理过 inf。无论如何,我认为编译器没有检查来确定整数/双精度数的穷举
  • 不相关:-(Double.infinity)..&lt;0.9 可以写成..&lt;0.9
  • 嗯,你可以不用default 来做到这一点,只需使用case _: 匹配任何东西,但我知道这也不是你想要的。

标签: swift switch-statement


【解决方案1】:

没有because only enum types can be exhaustively checked

但在这种情况下,问题就更深了。即使可以彻底检查整数,仍然如果没有 where 子句,您也无法彻底检查 Double。其中一个选项是.nan(“不是数字”),您没有考虑。所以你可能会想只添加这种情况:

case .nan:
    yAxisMinimum = .nan

这不仅不会使其详尽无遗,甚至不会按您期望的方式工作。

var minY = Double.nan

switch minY {
case -(Double.infinity)..<0.9:
    yAxisMinimum = 0.0
// ...
case .nan:
    yAxisMinimum = .nan
default:
    yAxisMinimum = 0
}

yAxisMinimum // 0

为什么?正因为如此:

var minY = Double.nan
minY == .nan   // false

NaN 不等于一切,包括 NaN。所以没有办法将它直接包含在 switch 语句中。您必须使用where 子句:

case _ where minY.isNaN:
    yAxisMinimum = .nan

绝对超出了编译器的验证能力。

【讨论】:

  • Rob - 您的回答提出了一个很好的观点,但是除了 eNums 之外,Swift 中肯定还有一些不需要默认值的东西。这是直接来自参考手册 (5.1) 的示例: let anotherPoint = (2, 0) switch anotherPoint { case (let x, 0): print("on the x-axis with an x​​ value of (x)") case (0, let y): print("在 y 轴上,y 值为 (y)") case let (x, y): print("在其他地方 ((x), (y))") } // 在 x 轴上打印“x 值为 2”
最近更新 更多