エラーと早期リターンでのdefer
throwや早期returnの場合でもクリーンアップを確実に行います。
「エラーと早期リターンでのdefer」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全4レッスンが含まれています。
return時にもdeferは実行される
関数がreturnによって早期に終了する場合でも、deferブロックは実行されます。
func check(_ value: Int) {
defer { print("cleanup ran") }
if value < 0 {
print("negative, returning early")
return
}
print("value is", value)
}
check(-5)すべての経路での後処理
どのreturnが実行されても、deferによる後処理は必ず1回だけ実行されます。
func classify(_ n: Int) {
defer { print("done classifying") }
if n == 0 { print("zero"); return }
if n > 0 { print("positive"); return }
print("negative")
}
classify(0)throw時にもdeferは実行される
関数がエラーをthrowした場合でも、登録されたdeferはスコープが巻き戻される際に実行されます。
enum MyError: Error { case bad }
func risky(_ fail: Bool) throws {
defer { print("cleanup on the way out") }
if fail { throw MyError.bad }
print("no failure")
}
try? risky(true)returnとthrowの組み合わせ
関数が通常どおり戻る場合でもthrowする場合でも、同じdeferが実行されます。
enum E: Error { case oops }
func op(_ flag: Bool) throws -> Int {
defer { print("op finishing") }
if flag { throw E.oops }
return 42
}
let r = try? op(false)
print(r ?? -1)エラーが伝播する前の後処理
deferはthrowされたエラーが呼び出し元に到達する前に実行されるため、先にリソースが解放されます。
enum E: Error { case fail }
func load(_ broken: Bool) throws {
print("open")
defer { print("close") }
if broken { throw E.fail }
print("read")
}
do {
try load(true)
} catch {
print("caught:", error)
}deferによるguard
よくあるパターンは、取得、deferによる後処理の登録、そしてguardによる検証です。早期returnが発生しても、後処理は実行されます。
func process(_ items: [Int]) {
print("start")
defer { print("finished") }
guard !items.isEmpty else {
print("nothing to do")
return
}
print("processing", items.count, "items")
}
process([])deferとエラーをthrowするループ
ループ内のdeferは、後続の文がエラーをthrowする場合でも、各反復の終了時に実行されます。
enum E: Error { case stop }
func loop() throws {
for i in 1...3 {
defer { print("end", i) }
if i == 2 { throw E.stop }
print("body", i)
}
}
try? loop()早期return時の実行順序
早期returnの場合でも、複数のdeferはLIFO順で実行されます。
func multi(_ skip: Bool) {
defer { print("A") }
defer { print("B") }
if skip { return }
print("body")
}
multi(true)失敗時のログ記録
deferを使うと、すべての終了経路で完了または失敗を一貫して記録できます。
enum E: Error { case bad }
func attempt(_ fail: Bool) throws {
var success = false
defer { print("attempt success:", success) }
if fail { throw E.bad }
success = true
}
try? attempt(true)throw時の状態復元
deferは、処理がthrowしたときに一時的な状態を元へ戻すのに適しています。
enum E: Error { case fail }
func transaction(_ fail: Bool) throws {
var inProgress = true
defer { inProgress = false; print("inProgress:", inProgress) }
if fail { throw E.fail }
print("committed")
}
try? transaction(true)ベストプラクティス
早期returnやthrowされたエラーが発生しても必要な後処理が行われるよう、deferに任せます。これにより、どの終了経路でもリソースがリークしません。
enum E: Error { case x }
func safe(_ fail: Bool) throws {
print("acquire")
defer { print("release") }
if fail { throw E.x }
print("use")
}
try? safe(true)確認問題
エラーとreturnがある場合のdeferを確認します。
まとめ
deferは、早期のreturnやthrowされたエラーを含め、スコープを抜けるたびに実行され、エラーが伝播する前に処理されます。そのため、すべての終了経路で後処理と状態復元を行う信頼できる場所となり、LIFO順も維持されます。
func f(_ skip: Bool) {
defer { print("cleanup") }
if skip { return }
print("work")
}
f(true)よくある質問
「エラーと早期リターンでのdefer」レッスンは無料ですか?
はい。「エラーと早期リターンでのdefer」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。
「エラーと早期リターンでのdefer」で何を学びますか?
throwや早期returnの場合でもクリーンアップを確実に行います。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Swift Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「エラーと早期リターンでのdefer」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このSwift Academyレッスンでコードを書いて実行できますか?
はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- deferの仕組み
- 複数のdeferブロックの実行順序
- リソース解放のためのdefer
- エラーと早期リターンでのdefer