2009-12-03 3 views
0

У меня есть некоторый код, который структурирован как следующее:Использование Goto для улучшения принципа DRY и четкости кода: хорошая идея?

if (someStatement) 
{ 
    //... 
    if (SomeOtherStatement) 
    { 
     //..., possibly more cases like this 
    } 
    else 
    { 
     //goto warning; 
     //would otherwise repeat 
     //the MessageBox.Show here 
    } 
} 
else 
{ 
    //goto warning; 
} 
//... 
warning: 
MessageBox.Show("some warning"); 

Как я отрекаюсь копированием кода, это один из немногих полезных применений Готы или есть лучше структура я могу использовать?

+0

Почему бы просто не написать метод ShowWarning и назвать его дважды? – RichardOD

+9

Довольно уверен, что именно поэтому программисты изобрели методы. –

+1

Но вы заметите, что все, что я делаю, вызывает один метод, который приводит меня к вопросу в первую очередь :) – RCIX

ответ

5

Как насчет этого?

if (someStatement) 
{ 
    //... 
    if (SomeOtherStatement) 
    { 
     //..., possibly more cases like this 

     return; // in the inner-most case 
    } 
} 

MessageBox.Show("some warning"); 
+0

+1, со структурой OP показал, что операторы * else * были излишними. – slugster

+0

С OP '// ...' между финальным блоком 'else' и предупреждающей меткой этот механизм не будет работать. –

+0

Мне повезло, и мне не нужно было ничего делать, но я буду пересматривать дизайн, если я это сделаю. – RCIX

0

Я лично считаю централизованное управление ошибками «почти единственным случаем», где goto является приемлемым. Однако для лучшей структуры я бы поставил ярлык полностью вне другого, в самом конце вашей функции.

+0

Да, мой goto не видит этикетку как есть. – RCIX

0

Вы видите одно и то же сообщение об ошибке на обеих линиях? Затем вы должны написать функцию, которая вызывает только эту строку, и вызывать эту функцию в обоих случаях.

if (someStatement) 
{ 
    //... 
    if (SomeOtherStatement) 
    { 
     //..., possibly more cases like this 
    } 
    else 
    { 
     showError(); 
    } 
} 
else 
{ 
    showError(); 
} 

ОТВЕТ: Это плохой пример, его можно решить с помощью одной ветви else, улавливающей ошибку. Вот лучше один:

if (!doSomething()) 
{ 
    showError(); 
} 
doSomethingElse(); 
if (!anotherCall()) 
{ 
    showError(); 
} 
+0

Именно поэтому я отправляю на SO: я обычно получаю несколько ответов на идеи, о которых я даже не думал :) – RCIX

+0

Хотя, кажется, почти бессмысленно иметь одну функцию, единственной целью которой является вызов другой функции с некоторыми заданными параметрами, похоже, например, для обфускации кода. – RCIX

+0

Я так не думаю, если вы назовете это хорошо, он будет использовать вашу цель ('DRY'), не нарушая читаемости. – soulmerge

2

Да, но только если по goto вы имеете в виду «создать функцию и вызвать ее несколько раз».

+1

метод извлечения - новый goto –

+0

goto намного лучше для программирования в реальном времени. –

1

лучший подход зависит от того, как выглядит остальная часть вашего кода. если код показан последний код в этом методе:

if(someStatement) { 
    // ... 
    if(SomeOtherStatement) 
    { 
     // a couple of lines of code 
     return; // ! 
    } 
} 

MessageBox.Show("someWarning"); 

, если нет, то вы, вероятно, придется возразить что-то вроде этого:

if(someStatement) { 
    // ... 
    if(SomeOtherStatement) 
    { 
     // a couple of lines of code 
    } 
    else 
    { 
     showWarning("not someOtherStatement"); 
    } 
} 
else 
{ 
    showWarning("not someStatement"); 
} 
0

Исключением являются правильный способ обработки ошибок в .NET , выбросить их, но и использовать их с умом:

try 
{ 
    if (someStatement) 
    { 
     //... 
     if (SomeOtherStatement) 
     { 
      //..., possibly more cases like this 
     } 
     else 
     { 
      throw new MyException(); 
      //would otherwise repeat 
      //the MessageBox.Show here 
     } 
    } 
} 
catch(MyException e) 
{ 
    MessageBox.Show(e.Message); 
    // log the exception, if necessary 
} 
finally 
{ 
    // tidy up 
} 

за исключением вы получаете сильно типизированный ответ на то, что пошло не так, которые вы можете легко реализовать в системы регистрации.

+4

Мне не нравится это использование исключений. Это использует исключения для управления потоком и хуже, чем использование goto (не то, что goto является правильным решением здесь). Существуют другие команды перехода, которые лучше подходят для этого случая (а именно, вызов функции, в зависимости от контекста). Кроме того, можно просто установить строковое сообщение об ошибке в случаях else и показать сообщение, если строка установлена. Обратите внимание, что если логика, которая может генерировать эти исключения, инкапсулируется в функцию или класс, исключения могут быть (и, вероятно,) подходящим выбором. –

0

Если вы собираетесь вступить в глубокую неприятную инструкцию по тестированию ошибок, как и у вас, то вам может потребоваться обернуть ее с помощью одного try/catch и выбросить соответствующие исключения для конкретного приложения из инструкции if. поймать те конкретные исключения в блоке catch, позволяя всем остальным поймать дальше цепочку.

0

Поскольку (начиная с FrameWork 1.1) логический и «& &«: »оценивает только свой второй операнд, если необходимо».

Что случилось с:

if(someStatement && someOtherStatement) 
{ 
     // more whatever 
} 
else 
{ 
     // raise an exception, call a method, show messagebox, whatever 
} 

В зависимости от сложности логической оценки происходит, если первое условие вычисляется как истина: и вы, возможно, реализовать множество других тестов, любое число которых может привести к в ошибках: все из которых вы хотите обрабатывать одинаковым образом: я бы счел обязательным либо поднять конкретное исключение, вызвать метод для обработки ошибки, либо поместить все это в блок try-catch (который может быть довольно уродливым, если есть много кода).

Метод с низким уровнем заглушки, который я использовал бы, если бы разумная презумпция того, что вероятность ошибки была довольно удаленной в 99% случаев, когда был вызван код: я бы установил булевский флаг, чтобы отразить состояние ошибки: оцените его при завершении сложного блока кода и сделайте то, что нужно сделать: конечно , если ваш код отлучается где-то в результате этих внутренних оценок: это не будет хорошо.

0

Я думаю, что goto - плохая идея. Если вам нужно прыгать, бросьте исключение, как было предложено joshcomley; если вы просто хотите вывести предупреждающее сообщение, но продолжайте без прыжка, вызовите метод.

+0

Но вся причина, по которой я прыгал, заключалась в том, чтобы уменьшить количество раз, когда я вызвал метод со строковой константой ... – RCIX

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