2015-06-01 2 views
2

У меня есть программа, которая полностью функциональна, и теперь я реорганизую ее. Я просто изучаю C#, поэтому исходный код был довольно ужасным, несмотря на то, что он прошел отлично. Одним из требований программы является то, что пользователь сможет вернуться в главное меню в любой момент. Я совершил это следующим образом:Решение для злоупотребления фразами?

static bool bouncer = false 
static void Exit(string input) 
{ 
    if (input == "\t") 
    { 
     bouncer = true 
    } 
} 
static string Prompt(string msg) 
{ 
    // takes input and passes it to Exit() then returns the input 
} 
static string FunctionA() 
{ 
    while(true) 
    { 
     if (bouncer == true) 
     { 
      break; 
     } 
     Prompt("whatever") 
     if (bouncer == true) 
     { 
      break; 
     } 
     Prompt("whatever") 
     if (bouncer == true) 
     { 
      break; 
     } 
     // return some stuff 
    } 
} 
static void Main() 
{ 
    bouncer = false 
    // writes the menu to console and handles UI 
    // FunctionA 
{ 

Переменный Вышибала получает значение истины, если пользователь вводит «вкладку» символ в любой точке входа. Распространение условных выражений break предоставляет структуру, которая фактически вырывается обратно в Main(). Это, очевидно, не очень хорошее решение, и это делает код трудным для чтения.

Других попыток, которые я считал для выполнения тех же задач являются:

  1. Goto утверждение, что прыгает прямо обратно в Main(). Я отказался от этого, потому что goto имеет очень ограниченную область действия в C#, и я не думаю, что есть хороший способ сделать его работоспособным в этой ситуации.

  2. Вызов Main() непосредственно из Exit(). Вероятно, это плохая идея, и я никак не могу это сделать, потому что, по-видимому, Main() «защищен» каким-то образом.

  3. Использование события для реагирования на нажатие TAB или ESC. Мне непонятно, как я могу использовать событие, чтобы сделать это, так как я все еще не смог бы вырваться из этого события. Я понимаю, что оператор break должен фактически содержаться в цикле, который нужно сломать, а не записываться в другую функцию, вызываемую из цикла.

Любые предложения приветствуются. Я надеюсь, что что-то будет сделано с обработкой событий или что я упустил что-то более простое. Благодаря!

+3

Вместо этого вы можете попробовать http://codereview.stackexchange.com/. – tnw

+0

Спасибо. Я не знал об этом! –

+0

Это консольная программа? Если да, зачем внедрять меню из командной строки? И Winform, и Webforms сделали бы это нить. и для этого они были созданы. – RBarryYoung

ответ

1

В отношении стиля кодирования, как это работает, но считается уродливым. К сожалению, если вам нужно немедленно прорваться между разделами работы, этого не так много.

Вы можете изменить текущий формат использования перерывов на использование стиля управления «if(bContinue) { /* do next section of work */ }». Он изменяет код с перерыва из цикла в то время как к этому:

static string FunctionA() 
{ 
    bool bContinue = true; 
    while(true == bContinue) 
    { 
     // Do initital work. 
     // 
     // Initial work can set bContinue to false if any error condition 
     // occurs. 

     if(true == bContinue) 
     { 
      // Do more work. 
      int returnCheck = MakeACall(); // Presume MakeACall returns negative interger values for error, 0 or positive values for success or success with condition/extra information. 
      if(0 < returnCheck) 
      { 
       bContinue = false; 
      } 
     } 

     if(true == bContinue) 
     { 
      Prompt("whatever") 
      // Do more work. 
      bContinue = MakeASecondCall(); // Presume that MakeASecondCall returns true for success, false for error/failure 
     } 

     if(true == bContinue) 
     { 
      Prompt("whatever") 
      // Do more work. 
      // If error encountered, set bContinue to false. 
     } 

     if(true == bContinue) 
     { 
      Prompt("whatever else") 
      // Do more work. 
      // If error encountered, set bContinue to false. 
     } 

     // Done with loop, so drop out. 
     bContinue = false; 
     // return some stuff 
    } 
} 

Глядя на ваш псевдокоде, он читает, как вы делаете только один проход через рабочий цикл. Если это так, вы можете переключиться на формат Do-While(false) и использовать разрывы, чтобы просто опуститься вниз. Или, если вы делаете только один проход через свой FunctionA, просто покончите с структурой управления While или Do-While и просто используйте if(true==bContinue){ /* Do more work */ }. Это не самый чистый код, но когда вы выполняете длительные периоды серийной работы, вы получаете такие структуры, если не собираетесь использовать while или do-while для управления потоком.

Недостаток использования if(bContinue){} стиля является то, что, когда состояние ошибки возникает на ранних стадиях процесса, код не выходит, как быстро из функции как break из-за while() или do-while() структуры, если ошибка происходит в верхней части работы, так как будет серия операторов if, что код будет проверяться, а затем пропустить. Но это читаемо, и если вы используете описательное имя для вашей управляющей переменной (то есть nContinue или bContinue или workLoopControl), должно быть достаточно очевидно, что это флаг главного управления для потока работы функции для тех, кто работает или просматривает код после вы.

+0

Я реализую этот стиль. Это действительно не работает иначе, чем мой оригинальный код, но реорганизация его таким образом по крайней мере улучшает читаемость :) –

1

Вместо операторов бесконечного цикла и разрыва попробуйте вместо этого использовать условный флаг.

static void FunctionA() 
{ 
    bool done = false; 
    string response = string.Empty; 
    while (!done) 
    { 
    response = Prompt("whatever"); 
    if(response == '\t') 
    { 
     done = true; 
    } 
    } 
} 

Как примечание стороны, я не знаю, почему у вас есть «строка» как тип возвращаемого из нескольких методов (например, «FunctionA»), когда вы не используете возвращаемое значение. Вот почему код, который я дал выше, имеет его как «пустое».

+0

Похоже, что OP просто прокомментировал раздел кода, который '// возвращает некоторые вещи' –

+0

FunctionA, а остальные возвращают материал в реальной программе. Я просто не думал писать их в качестве пустоты для фиктивного кода. Это решение имеет большой смысл, хотя у меня сложилось впечатление, что условное значение цикла while будет оцениваться только с каждой итерацией цикла. Это неправильно? –

+0

Это правильно. Если вам нужно выйти из MIDDLE цикла while, вам нужно использовать перерыв, как показано в примере вашего опубликованного кода в вопросе. – StarPilot

Смежные вопросы