Ошибка компилятора при сравнении значений типа 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()
Другие вопросы по тегам