当前位置: 首页 > 科技观察

Swift中NilCoalescing运算符的使用技巧

时间:2023-03-12 01:12:44 科技观察

在Swift官方文档《The Swift Programming Language》的BasicOperators部分,添加了NilCoalescingOperator的总结,引入了一个新的运算符NilCoalescing。符号是??,其表现形式如下:letc=a??b这个运算符有两个条件:a.它必须是可选类型。b的类型。必须与a的解包值类型一致。满足这两个条件后,再解释一下上面这行代码,意思就是c的值就是a或者b的值,但是有一个前提条件,就是拆包后a的值不为nil,那么a的解包值赋值给c,如果a的解包值是nil,那么b的值赋值给c。我们也可以用三元运算来更形象地解释这个运算符:letc=a!=nil?a!:b从上面的代码我们很容易理解,当a的值不等于nil时,拆包a之后b的值赋给c,否则b的值赋给c。我们来看看官方的代码示例:letdefaultColorName="red"varuserDefinedColorName:String?//默认值为nilvarcolorNameToUse=userDefinedColorName??defaultColorName//因为userDefinedColorName的值为nil,colorNameToUse的值为"red"userDefinedColorName="green"colorNameToUse=userDefinedColorName??defaultColorName//因为userDefinedColorName的值不为nil,所以colorNameToUse的值为"green"看到这里应该对NilCoalescing运算符有了清晰的认识,但是在实际使用中,我们还需要注意以下几点。对于编译器中的类型匹配原则,见谅在最后补充;,只是一种编码习惯==||先看一段代码:leta:Int?=nil;letb:Int?=7;letc=a!=nil?a!:b;//因为a的默认值为nil,所以c的值为{Some7}letd=a??b;//这里d的值为nil,这是怎么回事?首先,我们需要注意的是,官方文档中有这么一句话:“表达式b必须匹配a里面存储的类型”。但是在上面的代码例子中,我们的b是Int类型的?那么这个时候我们的编译器会做什么呢?我们通过自己实现一个NilCoalescing运算符来说明。代码片段如下:infixoperator???{associativityright;precedence110;}func???(a:T?,b:@autoclosure()->T)->T{returna!=nil?a!:b();}letd=a???b;//这里d的值还是nil从上面的代码片段我们可以看出a的类型是根据a的类型来决定的输入b,那么当我们传入的b是Int?类型时,编译器其实是自动将a的类型转换为Int??的类型,即Optional(a),那么我们就可以解释letd=a??b;这行代码。由于a==nil但Optional(a)!=nil,d=Optional(a)!,d的值为nil。NilCoalescing运算符的返回值类型。先看示例代码片段:leta:Int?=nil;letb:Int?=5;letc:Int?=6;//因为a的默认值为nil,设置b的值被赋值tox,x的值为{Some5},类型为Int?letx=a!=nil?a!:b;//因为c的值不为nil,所以将c解包后的值赋值给y,但是y的值是{Some6}而不是6,这是怎么回事?lety=c!=nil?c!:b;根据我们上面提到的编译器中的类型判断原理,可以理解,因为b的类型是Int?,所以c的类型就变成了Int??,所以Int的解压类型??是Int?如果我们声明了变量y的类型,编译器会抗议://a怎么可能是Int类型的?,那么编译器是不会通过的,因为这会导致赋值运算符两边的类型不相等letx:int=a!=nil?a!:b;//这种写法和上面一样,不会编译lety:Int=a??b;