4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Swift】switchではなくてif caseを使う理由

Last updated at Posted at 2021-07-19

switchではなくて、if caseを使うサンプルコードをたまに目にします。
なんでだろう?と思ったので調べた際のメモを残しておきます。

指摘事項あればドシドシください!

結論

switchのほうが一般的に可読性は高いが、if caseのほうが簡潔にコードを記載できる場合があるから。

記事を漁ると上記の理由のために使っていると言う意見がチラホラありました。
なのでそう言うことなのだと思います。

検証1

言葉だけだと分かりづらいので、サンプルコードを試します。

以下の2つのサンプルコードだと、if caseもswitchも同じ結果になります。

if_case_sample1.swift
let value = 1

if case 0 ..< 10  = value {
    print("match")
} else {
    print("not match")
}
// match

switch value {
case 0 ..< 10:
    print("match")
default:
    print("not match")
}
// match
if_case_sample2.swift
enum Drink {
    case Coffee
    case Water
}

let drink = Drink.Coffee

if case .Coffee  = drink {
    print("coffee")
} else if case .Water = drink {
    print("water")
}

switch drink {
case .Coffee:
    print("coffee")
case .Water:
    print("water")
}

// coffee

ん〜、switchのほうが読みやすい気がします。

しかし、switchのように常に分岐して判定しなければならないと言う場面ばかりではありません。
この条件のとき、これをしたいと言うときにswitchは重装です。

switchは仕様上、全てが網羅されるようにcaseを書かないといけません。
defaultも分岐先を作るためのcaseみたいなものですし。多分。

つまり、if case文であれば、else ifやelseを書かなくても、
この条件のとき、これをしたいと言う願いを簡潔に実装できると言う訳です。

以下、サンプルコードです。

if_case_sample1.swift
let value = 1

if case 0 ..< 10  = value {
    print("match")
}
// match

switch value {
case 0 ..< 10:
    print("match")
default:
    print("not match")
}
// match
if_case_sample2.swift
enum Drink {
    case Coffee
    case Water
}

let drink = Drink.Coffee

if case .Coffee  = drink {
    print("coffee")
} 

switch drink {
case .Coffee:
    print("coffee")
case .Water:
    print("water")
}

// coffee

上記サンプルコードだけだとあまりありがたみがないですが、
分岐が多い場合やシンプルに条件分岐したい時にありがたさを発揮するのが分かるかと思います。

余談1(guard caseもあるよ)

if caseだけでなく、guard caseってのもあります。
使い方は、if caseと一緒です。

サンプルコードです。

if_case_sample3.swift
enum APIResponseType{
    case Success(data: String, statusCode: Int)
    case Error(data: String, statusCode: Int)
}

let result = APIResponseType.Success(data: "成功!!!", statusCode: 200)

if case .Success(let data, let statusCode) = result {
    print("statusCode: \(statusCode)")    
    print("data: \(data)")
    // 通信が成功した時の処理を記載
    // ~~
}
guard_case_sample1.swift
enum APIResponseType{
    case Success(data: String, statusCode: Int)
    case Error(data: String, statusCode: Int)
}

let result = APIResponseType.Success(data: "成功!!!", statusCode: 200)

func test(){
    guard case .Success(let data, let statusCode) = result else {
        return
    }
    print("statusCode: \(statusCode)")
    print("data: \(data)")
    // 通信が成功した時の処理を記載
    // ~~
}

test()

余談2(パターンマッチは ~= を使うこともあるよ)

パターンマッチは ~= を使うこともあります。
if caseのcaseを外して、= を ~= に変更するだけです。

sample.swift
let value = 1

if 0 ..< 10  ~= value {
    print("match")
}
// match

enum Drink {
    case Coffee
}

let drink = Drink.Coffee

if .Coffee ~= drink {
    print("coffee")
}
// coffee

最後に

超基本的なことなんだろうし、モヤモヤがすっきりしたので良しとしよう!
同じような疑問の方の助けになっていたらなお良し!

本記事に対するコメントをいただいています。
実際に現場レベルで利用するときのことにも言及されているので、一読いただけると理解が深まると思います!

参考サイト

https://useyourloaf.com/blog/swift-if-case-let/
https://medium.com/swift-column/if-guard-case-529af6a50351
https://qiita.com/mono0926/items/f2875a9eacef53e88122#guard-case%E6%96%87
https://negichou.com/swift-enum-if-equatable/

4
5
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?