【问题标题】:Switch on Array type开启数组类型
【发布时间】:2018-03-21 12:45:27
【问题描述】:

概述

我想通过匹配数组类型来使用 switch 语句。我有以下课程。

类:

class A {}    
class B : A {}

开启单值工作:

let a : A = B()

switch a {
case let b as B:
    print("b = \(b)")
default:
    print("unknown type")
}

开启数组(编译错误):

let aArray : [A] = [B(), B()]

switch aArray {
case let bArray as [B] :
    print("bArray = \(bArray)")
default:
    print("unknown type")
}

错误:

Downcast pattern value of type '[B]' cannot be used

注意:Swift 4

上测试

问题:

  • 我怎样才能做到这一点?

【问题讨论】:

  • 似乎是一个已知问题:bugs.swift.org/browse/SR-5671,也在这里观察到:stackoverflow.com/questions/24355513/…
  • @MartinR 感谢您的更新,不确定条件一致性(Swift 4.1)是否会有所帮助,但似乎是一个开放的错误
  • @Hamish 是的,我什至可以改用is,但后来我想在此过程中将其转换为[B]。目前我认为没有办法将其转换为[B]
  • @Hamish 我的错,我没有正确阅读您的评论,它确实工作正常。我只是感到困惑。所以as Any只是为了抑制编译错误?
  • 您能否通过提及解决方法和错误将其发布为答案,以便帮助其他面临相同问题的人。非常感谢

标签: swift switch-statement


【解决方案1】:

在 Swift 4.1 中,您会收到更好的错误消息(感谢#11441):

未实现强制转换模式中的集合向下转换;改为使用显式向下转换为 '[B]'

简而言之,您遇到了一些尚未完全实现的编译器,其进度由错误 SR-5671 跟踪。

但是,您可以通过在执行强制转换之前强制转换为 Any 来解决此限制:

class A {}
class B : A {}

let aArray : [A] = [B(), B()]

switch aArray /* or you could say 'as Any' here depending on the other cases */ {
case let (bArray as [B]) as Any:
  print("bArray = \(bArray)")
default:
  print("unknown type")
}

// bArray = [B, B]

为什么会这样?首先,一点背景知识。数组、字典和集合由 Swift 的强制转换机制特别处理 - 尽管是泛型类型(默认情况下是不变的),Swift 允许您在不同元素类型的集合之间进行强制转换(请参阅this Q&A 了解更多信息)。

实现这些转换的函数驻留在标准库中(例如,Arrayimplementation is here)。在编译时,Swift 将尝试识别集合向下转换(例如您的示例中的 [A][B]),因此它可以直接调用上述转换函数,而不必进行 full 动态转换通过 Swift 运行时。

但是问题是,这个专门的逻辑没有实现集合向下转换模式(例如在您的示例中),因此编译器会发出错误。通过首先强制转换为 Any,我们强制 Swift 执行完全动态的转换,该转换通过运行时调度,最终将调用上述转换函数。

尽管在必要的专门逻辑到位之前,为什么编译器不能暂时将此类转换视为完全动态转换,但我不太确定。

【讨论】:

  • 我用字典而不是数组尝试了这个。如果您在 switch 块测试中有多个案例,如果字典是不同类型的,那么在我的测试中,行为可能是不可预测且不可靠的,尤其是在字典为空的情况下。斯威夫特也会抱怨其他情况下黄色是多余的!警告。因此,请务必小心,并在提交之前在您的实现中彻底测试它。
  • @stef 您能否详细说明您在使用字典时遇到的不可预测的行为? “案例已由以前的模式处理;考虑删除它”警告您收到 is a bug will be fixed in Swift 4.2。此外,如果字典为空,则可以将其转换为任何类型的字典(空数组和nil 可选项的行为相同)——SR-6192 的 cmets 对此进行了一些讨论。
猜你喜欢
  • 1970-01-01
  • 2019-02-15
  • 2015-06-21
  • 1970-01-01
  • 2011-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-13
相关资源
最近更新 更多