可选绑定评估可选(nil)的不需要的行为

Unwanted behaviour with optional binding evaluating optional(nil)

将 xCode 更新到版本 10(和 swift 4.2)后,我对可选绑定有一个奇怪的行为

代码如下,是读取json文件,T是泛型(这里是String

// Are there values for configName ?
if let values = cfg[configName] as? [String: Any] {

    print("0 - values[langCode!] = ", values[langCode!] ?? "null")
    print("1 - values[langCode!] as? T = ", values[langCode!] as? T)

    // is there a value for langCode ?
    if let value = values[langCode!] as? T {
        print("2 - value to return= ", value)
        return value
    } else {
        print("3 - Do something else ")
    }
}

在 xCode 9.4.1 和 Swift 4.1 中,我有以下日志:

0 - values[langCode!] =  null
1 - values[langCode!] as? T =  nil
3 - Do something else 

这就是我想要的,values[langCode!]nil 并且转换也是 return nil 所以 else 块被执行。

在 xCode 10 和 Swift 4.2 中,我有以下日志:

0 - values[langCode!] =  null
1 - values[langCode!] as? T =  Optional(nil)
2 - value to return=  nil

即使 values[langCode!] 为 "null".

,也会执行 if let 代码块

一个区别是 swift 4.2 values[langCode!] as? TOptional(nil) 而 Swift 4.1 values[langCode!] as? Tnil.

我检查了 version 4.2 的变更日志,但我看不到可以解释该行为的内容,我还检查了 JSONSerialization(用于序列化 json 文件)没有进行任何更改

有人在切换到 Swift4.2 时也遇到过这种情况吗? 有人有解释吗?还有解决方法?

在这种代码中使用可选绑定有什么好处?写 if (values[langCode!] != nil) {... 而不是可选绑定会不好吗?

谢谢

如果您没有更改代码并且它的行为有所不同,那么这可能是 Swift 中的错误。如果你能做一个小的测试用例,你应该在 https://bugs.swift.org.

提交错误

无论如何,这听起来像在 Swift 4.1 中,Swift 将类型 T 推断为一些非 Optional 类型(例如 Int),并且在 Swift 4.2 中,Swift 将 T 推导为 Optional(例如 Int?)。您可以通过添加以下语句进行检查:

print("Type T is bound to \(T.self)")

如果它在 Swift 4.1 下打印 Int(或其他),在 Swift 4.2 下打印 Optional<Int>,那就是问题所在。

我回答我的问题,因为评论中给出了正确答案。

Swift4.1 和 Swift4.2 之间观察到的差异是由于有意更改所致。 @Hamish 在这里解释了答案中的所有内容: