Я испытываю затруднения при выяснении, как убежать из цикла, который содержит оператор переключения. Повреждение убегает из переключателя, не цикла.
Существует, вероятно, более изящное решение этого. Я реализовал флаг, который начинается как верный и установлен на ложь и заканчивает цикл. Можно ли предложить лучшее решение?
Фон: этот код используется в системе организации технологических процессов штрихкода. У нас есть PocketPCs, которым встроили сканеры штрихкода. Этот код используется в одной из тех функций. Это предлагает пользователю различные части данных всюду по стандартной программе. Эта часть позволяет им просматривать путем прокрутки некоторые записи материально-технических ресурсов, отображающие ту информацию о терминале PocketPC (разбитые на страницы результаты), и позволяет им вводить "D" для Сделанного, "Q" для выхода.
Вот текущий пример C#, который должен быть улучшен:
do
{
switch (MLTWatcherTCPIP.Get().ToUpper())
{
case "": //scroll/display next inventory location
MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown();
break;
case "P": //scroll/display previous inventory location
MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown();
break;
case "D": //DONE (exit out of this Do Loop)
// break; // this breaks out of the switch, not the loop
// return; // this exists entire method; not what I'm after
keepOnLooping = false;
break;
case "Q": //QUIT (exit out to main menu)
return;
default:
break;
}
} while (keepOnLooping);
Вот пример кода, который делает это в VB.NET
Do
Select Case MLTWatcherTCPIP.Get().ToUpper
Case "" ''#scroll/display next inventory location
MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown()
Case "P" ''#scroll/display previous inventory location
MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextUp()
Case "D" ''#DONE (exit out of this Do Loop)
Exit Do
Case "Q" ''#QUIT (exit out to main menu)
Return
End Select
Loop
Спасибо,
Я нахожу эту форму еще более читабельной:
bool done = false;
while (!done)
{
switch (MLTWatcherTCPIP.Get().ToUpper())
{
case "": //scroll/display next inventory location
MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown();
break;
case "P": //scroll/display previous inventory location
MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown();
break;
case "D": //DONE (exit out of this Do Loop)
done = true;
break;
case "Q": //QUIT (exit out to main menu)
return;
default:
break;
}
}
Вы можете изменить операцию переключения на петлю for/foreach. После выполнения условия установите "keepOnLooping" в false, а затем используйте break для выхода из цикла. Остальное должно позаботиться о себе.
. IMO, это кажется совершенно прекрасным способом вырваться из петли , в то время как
. Он делает то, что вы ожидаете, без побочных эффектов. Я мог бы подумать о том, чтобы сделать
if(!keepOnLooping)
break;
, но это на самом деле не отличается с точки зрения исполнения.
.Оберните его в функцию и используйте оператор возврата для выхода. Как насчет этого?
Вы можете заменить оператор switch
на оператор if/else
. Нет необходимости в goto
и оператор break
выходит из цикла:
do
{
String c = MLTWatcherTCPIP.Get().ToUpper();
if (c = "")
MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown();
else if (c = "P")
MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextUp();
else if (c = "D")
break;
else if (c = "Q")
return;
else
{
// Handle bad input here.
}
} while (keepLooping)
Флаг - это стандартный способ. Единственный известный мне способ - использовать goto
.
Почему бы не обернуть переключатель в метод, который возвращает булева, чтобы продолжать петлевание? Это будет иметь дополнительное преимущество в том, что сделает код более читабельным. Есть причина, по которой кто-то написал статью о том, что нам все-таки не нужны goto statements ;)
do
{
bool keepOnLooping = TryToKeepLooping();
} while (keepOnLooping);
private bool TryToKeepLooping()
{
switch (MLTWatcherTCPIP.Get().ToUpper())
{
case "": //scroll/display next inventory location
MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown();
break;
case "P": //scroll/display previous inventory location
MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown();
break;
case "D": //DONE (exit out of this Do Loop)
// break; // this breaks out of the switch, not the loop
// return; // this exists entire method; not what I'm after
return false;
case "Q": //QUIT (exit out to main menu)
return true;
default:
break;
}
return true;
}
Для многоуровневых перерывов необходимо использовать оператор goto. Похоже, что это единственный "чистый" способ в C#. Использование флага также полезно, но требует дополнительного кода, если цикл имеет другие предикаты для выполнения.
http://msdn.microsoft.com/en-us/library/aa664756(VS.71).aspx
Может быть интересно заметить, что некоторые другие неязыковые языки имеют многоуровневые перерывы, делая break levels;
(Java также бесполезна, однако, как и использование goto, замаскированного под продолжение... :P)
Единственное, о чем я знаю, - это ужасное гото. MSDN также говорит об этом.
Однако, я не вижу причин, по которым вы бы использовали его в этом случае. То, как вы это реализовали, отлично работает и более удобно в обслуживании, чем goto. Я бы сохранил то, что у вас есть.
Одним из вариантов здесь является преобразование этого цикла в метод ("метод извлечения") и использование return
.
Я бы попытался избежать этого, но вы могли бы использовать...
Тем не менее, разгневанные толпы с вилками становятся профессиональной опасностью, если вы решите это сделать.
.