一般来说,我们会优先使用所谓的"early return"策略来避免if表达式中的多层嵌套的代码。
在这种情况下使用guard语句能够有效地提升代码的可读性。
// PREFERRED
func eatDoughnut(atIndex index: Int) {
guard index >= 0 && index < doughnutselse{
// return early because the index is out of bounds
return
}
let doughnut = doughnuts[index]
eat(doughnut)
}
// NOT PREFERRED
func eatDoughnuts(atIndex index: Int) {
if index >= 0 && index < donuts.count {
let doughnut = doughnuts[index]
eat(doughnut)
}
}
在对Optional类型进行解包的时候,优先使用 guard 语句来避免if语句中较多的缩进。
// PREFERRED
guard let monkeyIsland = monkeyIsland else{
return
}
bookVacation(onIsland: monkeyIsland)
bragAboutVacation(onIsland: monkeyIsland)
// NOT PREFERRED
if let monkeyIsland = monkeyIsland {
bookVacation(onIsland: monkeyIsland)
bragAboutVacation(onIsland: monkeyIsland)
}
// EVEN LESS PREFERRED
if monkeyIsland == nil {
return
}
bookVacation(onIsland: monkeyIsland!)
bragAboutVacation(onIsland: monkeyIsland!)
在决定是要用if表达式还是guard表达式进行Optional类型解包的时候,最重要的点就是要保证代码的可读性。很多时候要注意因时而变,因地制宜:
// an `if` statement is readable here
if operationFailed {
return
}
// a `guard` statement is readable here
guard isSuccessful else{
return
}
// double negative logic like this can get hard to read - i.e. don't do this
guard !operationFailed else{
return
}
当需要进行多可能性处理的时候,应该优先使用if表达式而不是guard表达式。
// PREFERRED
if isFriendly {
print("Hello, nice to meet you!")
}else{
print("You have the manners of a beggar.")
}
// NOT PREFERRED
guard isFriendly else{
print("You have the manners of a beggar.")
return
}
print("Hello, nice to meet you!")
一般来说,guard应该被用于需要直接退出当前上下文的情形。而对于下面这种两个条件互不干扰的情况,应该使用两个if而不是两个guard。
if let monkeyIsland = monkeyIsland {
bookVacation(onIsland: monkeyIsland)
}
if let woodchuck = woodchuck where canChuckWood(woodchuck) {
woodchuck.chuckWood()
}
有时候我们会碰到要用guard语句进行多个optionals解包的情况,一般而言,对于复杂的错误处理的Optional类型需要将其拆分到多个单个表达式中。
// combined because we just return
guard let thingOne = thingOne,
let thingTwo = thingTwo,
let thingThree = thingThreeelse{
return
}
// separate statements because we handle a specific error in each case
guard let thingOne = thingOneelse{
throwError(message: "Unwrapping thingOne failed.")
}
guard let thingTwo = thingTwoelse{
throwError(message: "Unwrapping thingTwo failed.")
}
guard let thingThree = thingThreeelse{
throwError(message: "Unwrapping thingThree failed.")
}
不要将guard表达式强行缩写到一行内。
// PREFERRED
guard let thingOne = thingOneelse{
return
}
// NOT PREFERRED
guard let thingOne = thingOneelse{return}