2015-09-02 3 views
2

В настоящее время у меня есть это:Swift: Переключить оператор проваливается поведение

let somePoint = (1, 0) 

switch somePoint { 
case (0,0): 
    print("origin") // does not print 
    fallthrough 
case (_, 0): 
    print("y-axis") // prints y-axis. this makes sense 
    fallthrough 
case(0, _): 
    print("x-axis") // prints x-axis (because of fallthrough? this should not print) 
    fallthrough 
case(-2...2, -2...2): 
    print("in 5x5 box about the origin") // this prints and makes sense 
default: 
    print("somewhere else") // does not print 
} 

Моя цель с этим переключателем заявлением должна иметь каждый случай печать, если это правда, и НЕ иметь только первый случай, когда сопоставляются печать. Я думал, что смогу сделать это с помощью проклятого заявления. Однако это заставило меня расспросить, как это работает. Почему провал автоматически печатает следующий случай в строке, даже если случай не совпадает? Как я могу заставить эту инструкцию switch работать так, как я ее хочу?

ответ

6

Fallthrough падает до следующего случая, а не к следующему совпадающему случае. Концепция наследуется от операторов C switch, где каждый case может считаться ярлыком назначения goto, а оператор switch приносит исполнение первому соответствующему.

В С в заявлении switch указывается только, где исполняется внутри блока. Для дополнительного удобства вы можете использовать инструкцию break, чтобы пропустить остальную часть тела switch, но ничто не заставляет вас; и если вы этого не сделаете, выполнение продолжается нормально, например, case s не было. Например:

switch (countdown) 
{ 
    case 3: puts("3..."); 
    case 2: puts("2..."); 
    case 1: puts("1..."); 
    case 0: puts("0!"); 
} 

С не break в любом месте, если countdown 3, то вы получите все это (даже если countdown очевидно 3, а не 2, 1 или 0).

Когда выполнение идет от случая к случаю, вместо выхода из switch сферы (например, с break заявления), вы получите «проваливаться» (что делает Swift fallthrough ключевое слово).

Это относится к C, поскольку вы можете использовать произвольно сложные структуры внутри операторов switch, если хотите. Вот правовая программа C: (!? Поспешностью еще ветвь может быть выполнена, если x == 1)

switch (x) 
{ 
    case 0: 
     if (y == 3) 
     { 
    case 1: 
      puts("hello"); 
     } 
     else 
     { 
      puts("world"); 
     } 

    case 2: 
     puts("!"); 
} 

Этот вид использования, однако крайне редко и часто трудно следовать. Я не тестировал, но был бы очень удивлен, если бы вы могли сделать что-то подобное с Swift.

В целом, в C, падение через считается плохой стиль, поскольку часто бывает трудно определить, является ли провал добровольным или из-за отсутствующего заявления break. Swift решает эту проблему с помощью инструкции fallthrough, в которой четко указывается, что вы хотите, чтобы выполнение продолжалось до следующего случая внутри оператора switch, а не выхода из области switch.

В вашем случае вы не можете использовать патрус, чтобы получить то, что хотите, потому что прорыв полезен только тогда, когда последовательность выполнения, которая вам нужна, является линейной.Вам нужно пропустить недопустимые блоки кода, поэтому вам нужно использовать последовательность if-else вместо инструкции switch.

+0

В C# он решается с помощью 'goto case X', легко читаемого без необходимости нового ключевого слова –

+1

@ LưuVĩnhPhúc, это возможно из-за ограниченной природы случаев C# (и C/C++/etc) (относительно Swift), а не то, что хочет OP. Они хотят перейти в другое дело * и начать поиск другого соответствия. * Случай C# goto не переоценивается, потому что критерии выбора не являются динамическими. Другими словами, вы уже должны знать, куда идете. – paxdiablo

2

Если вы хотите, чтобы провалиться в других соответствующих случаев, а не на следующий (как fallthrough делает), switch не является правильным инструментом для работы.

Вместо этого, вы должны использовать серию if утверждений, что-то вроде:

Bool gotOne = false; 
if (somePoint.0 == 0 && somepoint.1 == 0) { 
    print("origin") 
    gotOne = true; 
} 
if (somepoint.1 == 0) { 
    print("y-axis") 
    gotOne = true; 
} 
if (somepoint.0 == 0) { 
    print("x-axis") 
    gotOne = true; 
} 
: 
if (! gotOne) { 
    print("somewhere else") 
} 
Смежные вопросы