代码之家  ›  专栏  ›  技术社区  ›  Duncan C

“警卫让foo=foo”什么时候成为合法的?

  •  11
  • Duncan C  · 技术社区  · 8 年前

    早在2016年11月,我就发布了一个问题,问我为什么不能使用guard创建一个与可选变量同名的变量的展开版本,就像你可以使用if-let:

    链接: Why isn't guard let foo = foo valid?

    当我写这个问题时,下面的代码将无法编译,并出现“定义与以前的值冲突”的错误:

    //Test of using guard to create an unwrapped version of a var, like if let
    func guardTest(_ viewController: UIViewController?) -> UIViewController? {
      // Check if the current viewController exists
      print(String(describing: viewController))
      guard let viewController = viewController else {
        return nil
      }
      print(String(describing: viewController))
    
      return viewController
    }
    

    然而,我刚刚在工作中发现了一些这样做的代码,现在它可以毫无怨言地编译,并完成我想要它做的事情!运行时,print语句显示foo在保护之前是可选的,在保护之后是unwrapped可选的:

    viewController = Optional(<TrochoidDemo.ViewController: 0x7ff16a039a00>)
    viewController = <TrochoidDemo.ViewController: 0x7ff16a039a00>
    

    (我添加了测试功能 guardTest(_:) 如果你想试试我最新的开源项目。它可在Github上获得,网址: https://github.com/DuncanMC/TrochoidDemo )

    我很高兴这个构造现在能按我所希望的那样工作,但对于 为什么? 现在它是合法的,当改变发生时。

    有没有人知道最近语言定义的一个变化,使这个构造在以前没有的地方工作?

    1 回复  |  直到 8 年前
        1
  •  13
  •   vacawama    8 年前

    TL;博士

    guard let foo = foo 如果: foo 在另一个作用域中定义。


    链接问题中的示例:

    func test()
    {
      let a: Int? = 1
    
      guard let a = a else{
        return
      }
      print("a = \(a)")
    }
    

    仍然不起作用,因为 guard 语句正在尝试创建另一个变量 a 在相同的范围内。

    这个例子:

    //Test of using guard to create an unwrapped version of a var, like if let
    func guardTest(_ viewController: UIViewController?) -> UIViewController? {
      // Check if the current viewController exists
      print(String(describing: viewController))
      guard let viewController = viewController else {
        return nil
      }
      print(String(describing: viewController))
    
      return viewController
    }
    

    工作的原因与此相同:

    func test(a: Int)
    {
        print(type(of: a))  // Int
    
        let a = 3.14
    
        print(type(of: a))  // Double
    }
    

    函数的参数在不同的范围内定义,因此Swift允许您创建具有相同名称的局部变量。