Ошибка компилятора при сравнении значений типа enum с соответствующими значениями?
class MyClass
{
enum MyEnum {
case FirstCase
case SecondCase(Int)
case ThirdCase
}
var state:MyEnum!
func myMethod ()
{
if state! == MyEnum.FirstCase {
// Do something
}
}
}
Я получаю ошибку компилятора, указывающую на if
заявление::
Двоичный оператор '==' нельзя применить к двум операндам MyClass.MyEnum.
Если вместо этого я использую switch
С заявлением нет проблем:
switch state! {
// Also, why do I need `!` if state is already an
// implicitly unwrapped optional? Is it because optionals also
// are internally enums, and the compiler gets confused?
case .FirstCase:
// do something...
default:
// (do nothing)
break
}
Тем не менее switch
заявление кажется слишком многословным: я просто хочу do something
за .FirstCase
и ничего другого. if
утверждение имеет больше смысла.
Что происходит с перечислениями и ==
?
РЕДАКТИРОВАТЬ: Это ультра странно. После урегулирования для switch
версия и переход к другим (совершенно не связанным) частям моего кода, и возвращаясь, if
версия (сопоставление свойства force-unwrapped с фиксированным регистром перечисления) компилируется без ошибок. Я могу только заключить, что это как-то связано с поврежденным кешем в парсере, который был очищен по пути.
РЕДАКТИРОВАТЬ 2 (Спасибо @LeoDabus и @MartinR): Кажется, что ошибка появляется, когда я устанавливаю связанное значение для другого случая перечисления (не того, с которым я сравниваю - в данном случае,.SecondCase). Я до сих пор не понимаю, почему это вызывает эту ошибку компилятора, в частности ("Невозможно использовать бинарный оператор" == "..."), или что это значит.
2 ответа
Как вы сказали в комментарии, ваш тип перечисления действительно имеет связанные значения. В этом случае нет по умолчанию ==
оператор для типа enum.
Но вы можете использовать сопоставление с образцом даже в if
заявление (начиная со Swift 2):
class MyClass {
enum MyEnum {
case FirstCase
case SecondCase
case ThirdCase(Int)
}
var state:MyEnum!
func myMethod () {
if case .FirstCase? = state {
}
}
}
Вот .FirstCase?
это ярлык для .Some(MyEnum.FirstCase)
,
В вашем заявлении о замене, state
автоматически не разворачивается, даже если это неявно развернутый необязательный (иначе вы не могли бы сопоставить с nil
). Но тот же шаблон можно использовать здесь:
switch state {
case .FirstCase?:
// do something...
default:
break
}
Обновление: Начиная с Swift 4.1 (Xcode 9.3), компилятор может синтезировать соответствие Equatable/Hashable для перечислений со связанными значениями (если все их типы являются Equatable/Hashable). Достаточно заявить о соответствии:
class MyClass {
enum MyEnum: Equatable {
case firstCase
case secondCase
case thirdCase(Int)
}
var state:MyEnum!
func myMethod () {
if state == .firstCase {
// ...
}
}
}
class MyClass {
enum MyEnum {
case FirstCase
case SecondCase
case ThirdCase
}
var state: MyEnum!
func myMethod() {
guard
let state = state else { return }
if state == MyEnum.FirstCase {
// Do something
print(true)
} else {
print(false)
}
}
}
let myClass = MyClass()
myClass.state = .FirstCase
myClass.myMethod()
myClass.state = .SecondCase
myClass.myMethod()