Коли доцільно використовувати випадок (класичний) вимикач перемикача? Чи рекомендується та заохочується таке використання чи його слід уникати будь-якою ціною?
Коли доцільно використовувати випадок (класичний) вимикач перемикача? Чи рекомендується та заохочується таке використання чи його слід уникати будь-якою ціною?
Відповіді:
Ось приклад, де це було б корисно.
public Collection<LogItems> GetAllLogItems(Level level) {
Collection<LogItems> result = new Collection<LogItems>();
switch (level) {
// Note: fall through here is INTENTIONAL
case All:
case Info:
result.Add(GetItemsForLevel(Info));
case Warning:
result.Add(GetItemsForLevel(Warning));
case Error:
result.Add(GetItemsForLevel(Error));
case Critical:
result.Add(GetItemsForLevel(Critical));
case None:
}
return result;
}
Думаю, подібні речі (де один випадок включає інший) є досить рідкісними, тому деякі новіші мови або не дозволяють перепадати, або потребують спеціального синтаксису.
// INTENTIONAL FALL THROUGH HERE
коментаря з усіма кришками .
GetItemsForLevel(Info)
виклик дзвінка GetItemsForLevel(Warning)
тощо.
Я використовую їх, коли певна функціональність повинна застосовуватися для більш ніж одного значення. Наприклад, скажіть, у вас був об’єкт із властивістю під назвою OperationCode. Якщо код дорівнює 1, 2, 3 або 4, потрібно запустити OperationX (). Якщо це 5 або 6, потрібно запустити OperationY (), а 7 - startOperationZ (). Чому у вас є 7 повних справ із функціональністю та перервами, коли ви можете використовувати пропускні дані?
Я думаю, що це цілком справедливо в певних ситуаціях, особливо якщо він уникає 100 тверджень інше. =)
switch
декілька case
s, прив'язаних до одного коду. Це інакше, ніж провал, коли виконання одного case
продовжується в наступне через відсутність break
між ними.
Шафи, що пронизуються, прекрасно виглядають. Я часто виявляю, що перерахування використовується в багатьох місцях, і коли вам не потрібно розмежовувати деякі випадки, простіше використовувати логіку пропускання.
Наприклад (зверніть увагу на пояснювальні коментарі):
public boolean isAvailable(Server server, HealthStatus health) {
switch(health) {
// Equivalent positive cases
case HEALTHY:
case UNDER_LOAD:
return true;
// Equivalent negative cases
case FAULT_REPORTED:
case UNKNOWN:
case CANNOT_COMMUNICATE:
return false;
// Unknown enumeration!
default:
LOG.warn("Unknown enumeration " + health);
return false;
}
}
Я вважаю такий вид використання цілком прийнятним.
case X: case Y: doSomething()
та case X: doSomething(); case Y: doAnotherThing()
. У першому намір є досить явним, тоді як у другому провал може бути навмисним чи ні. На мій досвід, перший приклад ніколи не викликає попереджень у компіляторах / аналізаторах коду, тоді як другий. Особисто я б назвав лише другий приклад "провалитися" - але не впевнений у "офіційному" визначенні.
Це залежить від:
Дві основні проблеми, пов'язані з тим, щоб один випадок перейшов у інший, є:
Це робить ваш код залежним від порядку заяв справи. Це не так, якщо ви ніколи не пропадаєте, і це додає ступеня складності, яка часто є небажаною.
Не очевидно, що код для одного випадку включає код для одного або декількох наступних випадків.
Деякі місця прямо забороняють пробиватися. Якщо ви не працюєте в такому місці і якщо вам подобається практика, і якщо порушення коду, про який йде мова, не спричинить справжніх страждань, то це може бути не найгірше в світі. Якщо ви це зробите, не забудьте поруч поставити привертаючий увагу коментар, щоб попередити тих, хто прийде пізніше (включаючи майбутнього ви).
Ось швидкий (мабуть, неповний (без спеціального поводження з високосний рік)) приклад пропуску, який полегшує моє життя:
function get_julian_day (date) {
int utc_date = date.getUTCDate();
int utc_month = date.getUTCMonth();
int julian_day = 0;
switch (utc_month) {
case 11: julian_day += 30;
case 10: julian_day += 31;
case 9: julian_day += 30;
case 8: julian_day += 31;
case 7: julian_day += 31;
case 6: julian_day += 30;
case 5: julian_day += 31;
case 4: julian_day += 30;
case 3: julian_day += 31;
case 2: julian_day += 28;
case 1: julian_day += 31;
default: break;
}
return julian_day + utc_date;
}
Якщо я відчуваю потребу переходити від однієї справи до іншої (рідко, правда,), я вважаю за краще бути дуже чітким і goto case
, звичайно, маючи на увазі, що ваша мова це підтримує.
Оскільки падіння через таке явище нечасте, і дуже легко його не помітити під час читання коду, я вважаю, що доречно бути явним - і гото, навіть якщо це стосується справи, повинно виділятися, як болілий палець.
Це також допомагає уникнути помилок, які можуть виникнути, коли викладені випадки перепорядковані.