Swift: การทดสอบกับค่าทางเลือกในกรณีสวิตช์


94

ในสวิฟท์, วิธีการที่ฉันสามารถเขียนกรณีในงบสวิทช์ว่าการทดสอบเป็นค่าเปลี่ยนกับเนื้อหาของนั้นไม่จำเป็นกระโดดกว่าในกรณีที่จำเป็นมีnil?

นี่คือวิธีที่ฉันคิดว่าสิ่งนี้อาจมีลักษณะ:

let someValue = 5
let someOptional: Int? = nil

switch someValue {
case someOptional:
    // someOptional is non-nil, and someValue equals the unwrapped contents of someOptional
default:
    // either, someOptional is nil, or someOptional is non-nil but someValue does not equal the unwrapped contents of someOptional
}

ถ้าฉันเพียงแค่เขียนมันตรงเช่นนี้คอมไพเลอร์บ่นว่าsomeOptionalไม่ยังไม่ได้เปิด แต่ถ้าผมอย่างชัดเจนแกะได้โดยการเพิ่ม!ไปที่ปลายผมของหลักสูตรได้รับข้อผิดพลาด runtime เวลาใด ๆ ที่มีsomeOptional nilการเพิ่ม?แทนที่จะเป็นสิ่งที่!สมเหตุสมผลสำหรับฉัน (ในแง่ของการผูกมัดทางเลือกฉันคิดว่า) แต่ไม่ได้ทำให้ข้อผิดพลาดของคอมไพเลอร์หายไป (เช่นไม่ได้แกะตัวเลือก)

คำตอบ:


113

ทางเลือกมีenumดังนี้:

enum Optional<T> : Reflectable, NilLiteralConvertible {
    case none
    case some(T)

    // ...
}

คุณจึงจับคู่รูปแบบการจับคู่"ค่าที่เกี่ยวข้อง" ได้ตามปกติ:

let someValue = 5
let someOptional: Int? = nil

switch someOptional {
case .some(someValue):
    println("the value is \(someValue)")
case .some(let val):
    println("the value is \(val)")
default:
    println("nil")
}

หากคุณต้องการจับคู่someValueโดยใช้นิพจน์ยาม :

switch someValue {
case let val where val == someOptional:
    println(someValue)
default:
    break
}

และสำหรับ Swift> 2.0

switch someValue {
case let val where val == someOptional:
    print("matched")
default:
    print("didn't match; default")        
}

5
โปรดทราบว่าใน Swift 3 บางตัว / ไม่มีเป็นตัวพิมพ์เล็กเช่นคุณจะใช้. บางตัวแทนบางคน
อดัม

55

ตั้งแต่ Xcode 7 x?รูปแบบใหม่สามารถใช้เพื่อจับคู่กับตัวเลือกเป็นคำพ้องความหมายได้.some(x)ซึ่งหมายความว่าใน Swift 2 ขึ้นไปคำตอบของ rintaroรูปแบบต่อไปนี้จะใช้ได้เช่นกัน

let knownValue = 5

switch someOptional {
case knownValue?:
    // Contents of someOptional are knownValue, defined above.
case let otherValue?:
    // Contents of someOptional are *any* non-nil value not already tested for.
    // Unwrapped contents are assigned to otherValue for use inside this case.
default:
    // someOptional is nil.
}

3
คำถามเกี่ยวกับการจับคู่ค่าที่ไม่ใช่ทางเลือกกับตัวเลือกคำตอบนี้เป็นอีกทางหนึ่ง
Martin R

2
จริงอยู่อย่างไรก็ตามคำตอบนี้ถูกเขียนขึ้นโดย OP เพื่ออัปเดตคำถามดังนั้นสำหรับเขาแล้วมันเป็นทางออกที่หักล้างไม่ได้ ฉันเพิ่งย้ายไปที่คำตอบวิกิชุมชน บางที @GeorgeWS สามารถชี้แจงได้ว่าเหตุใดการสลับสวิตช์ & เคสจึงใช้ได้กับกรณีการใช้งานของเขา
Slipp D.Thompson

2
ฉันหลงทางนิดหน่อย 2 กรณีแรกของคุณแตกต่างกันอย่างไร someValue?เป็นค่าอื่น ๆ ที่กำหนดไว้ แต่case let val?เป็นเพียงรุ่นที่ไม่ได้ปิดกั้นที่ปลอดภัยของsomeOptional?!
น้ำผึ้ง

@ ฮันนี่ไม่ใช่ตัวอย่างโค้ดในโลกแห่งความจริง มันเป็นเพียงรูปแบบหนึ่งของคำตอบของ rintaro ไปถามเขา / เธอคำถามนั้น - คำตอบของฉันเทียบเท่ากับรหัสใน / เธอ ถ้าคุณถาม rintaro ฉันเชื่อว่าคำตอบจะเป็น 1. มันสะท้อนสิ่งที่อยู่ในเอกสารของ Apple ที่เชื่อมโยง 2. แสดงให้เห็นถึงไวยากรณ์เท่านั้น มันไม่บรรลุเป้าหมายการคำนวณที่แตกต่างกันหรือตรรกะทางธุรกิจ
Slipp D.Thompson

@Honey นอกจากนี้คำตอบของ rintaro เดิมเขียนขึ้นสำหรับ Swift 1.x และอัปเดตสำหรับ Swift 2 เป็นไปได้ว่าเวอร์ชันที่letไม่มีการคอมไพล์อีกต่อไป ตอนนี้ฉันจำไม่ได้แล้วว่าทำไมถึงได้ผลในวันนั้น
Slipp D.Thompson

10

ในSwift 4คุณสามารถใช้ทางเลือก: ExpressibleByNilLiteralของ Apple เพื่อห่อตัวเลือกได้

https://developer.apple.com/documentation/swift/optional

ตัวอย่าง

enum MyEnum {
    case normal
    case cool
}

บาง

let myOptional: MyEnum? = MyEnum.normal

switch smyOptional {
    case .some(.normal): 
    // Found .normal enum
    break

    case .none: 
    break

    default:
    break
}

ไม่มี

let myOptional: MyEnum? = nil

switch smyOptional {
    case .some(.normal): 
    break

    case .none: 
    // Found nil
    break

    default:
    break
}

ค่าเริ่มต้น

let myOptional: MyEnum? = MyEnum.cool

switch smyOptional {
    case .some(.normal): 
    break

    case .none: 
    break

    default:
    // Found .Cool enum
    break
}

Enum ด้วยค่า

enum MyEnum {
    case normal(myValue: String)
    case cool
}

คุณค่าบางอย่าง

let myOptional: MyEnum? = MyEnum.normal("BlaBla")

switch smyOptional {
case .some(.normal(let myValue)) where myValue == "BlaBla":
    // Here because where find in my myValue "BlaBla"
    break

// Example for get value
case .some(.normal(let myValue)):
    break

// Example for just know if is normal case enum
case .some(.normal):
    break

case .none:
    break

default:

    break
}

คุณพูดถึงExpressibleByNilLiteralแต่ที่ไม่ได้ใช้จริงในการประกาศ enum ฯลฯ นั่นคืออะไร?
pkamb
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.