为什么类型推断在Swift 3中的这个switch语句中不起作用?

时间:2016-11-15 17:50:27

标签: swift

UPDATE 这在Swift 3.1

中已得到修复

在将if-else迁移到switch语句时,我注意到类型推断不起作用。当HKQuantityTypeIdentifier已经属于该类型时,为什么我需要在每个case中指定quantityTypeIdentifier

func process(samples: [HKSample]?, quantityTypeIdentifier: HKQuantityTypeIdentifier) {
    DispatchQueue.main.async { [weak self] in            
        if let quantitySamples = samples as? [HKQuantitySample] {
            for sample in quantitySamples {
                switch quantityTypeIdentifier {
                case HKQuantityTypeIdentifier.distanceWalkingRunning:
                    // code

                case HKQuantityTypeIdentifier.activeEnergyBurned:
                    // code

                case HKQuantityTypeIdentifier.heartRate:
                    // code

                default:
                    fatalError("Quantity Type Identifier not implemented \(quantityTypeIdentifier)")
                }
            }
        }
    }
}

我可以调用函数:

process(samples: samples, quantityTypeIdentifier: .distanceWalkingRunning)

1 个答案:

答案 0 :(得分:3)

我认为你发现了一个错误,或者至少你有一个合理的案例要求一个。一个更短的例子很好地显示了不一致性:

let c : UIColor = .red
switch c {
case .red : print ("red") // error
default : break
}

那不会编译。你可以在第一行说.red但在第三行不说。{1}}。这似乎是一个明显的不一致。

现在,说了这些,我当然可以解释为什么规则在两个不同的地方有所不同。根据{{​​1}}运算符和形成模式的规则解析case表达式。这些规则与Swift中的任何其他规则都不同(例如,在某些情况下,您在~=模式中说as但在其他地方会说case。显然,这些是需要调整以使其工作的规则。它们已被调整到允许裸枚举的情况但不是简单的枚举结构“情况”(即,这些静态成员评估结构本身实例的RawRepresentable结构的静态成员)。

最后,当as?模式变得过于繁重时,我喜欢使用这种方法:

case

通过打开let c : UIColor = .red switch true { case c == .red : print ("red") // heh heh default : break } 并写出整个布尔条件,我们打破了模式匹配的界限,重新进入正常表达式的世界。