Если выбирать из двух предложенных вариантов, то вариант с goto предпочтительней:
1. На машинном уровне это одна инструкция прямой передачи управления, против раскрутки стека потока в случае с exception
2. Использовать exceptions для организации program flow — явный code smell.
И в любом случае, я бы постарался переписать и без goto,и без exceptions.
Здравствуйте, RushDevion, Вы писали:
RD>Если выбирать из двух предложенных вариантов, то вариант с goto предпочтительней: RD>1. На машинном уровне это одна инструкция прямой передачи управления, против раскрутки стека потока в случае с exception RD>2. Использовать exceptions для организации program flow — явный code smell. RD>И в любом случае, я бы постарался переписать и без goto,и без exceptions.
Нет тут никого control-flow на исключениях. Было бы лучше, если бы исключение(я) были более типизированными. Кмк, лучше чем вариант с goto в данном случае.
Правильней -- через exp, производительнее -- if.
Здравствуйте, #John, Вы писали:
J>какой код будет производительней/правильней писать(a именно в плане применять if или exception):
Использования try/catch для управления потоком исполнения программы (забавно flow control звучит по русски, наверное плохо перевел) это хорошо известный анти-паттерн. Если вы сами кидаете исключение или специально допускаете его его лишь для того, чтобы пропустить исполнение какого-то кода, то вы тот самый плохой программист.
В случае c# исключения прежде всего довольно "тяжеловесные". Из-за использования try/catch может ухудшиться читаемость когда (особенно, если они вложенные или уже находятся внутри вложенного блока кода).
Кроме того вы можете таким образом спрятать баг: ошибка, приводящая к unhandled exception и крашу (в хорошем смысле) программы, будет перехвачена и найти ее будет намного сложнее.
Использование goto в целом не рекомендуется, особенно новичкам: компилятор может производить более качественный код без него. Но не запрещено. Если вы ищете альтернативы, то можно использовать циклы с break, switch, флаги, state-machine и делегаты чтобы обойтись без goto и даже сделать логику более читаемой.
Здравствуйте, RushDevion, Вы писали:
RD> вариант с goto RD>1. На машинном уровне это одна инструкция прямой передачи управления, против раскрутки стека потока в случае с exception
А вложенные друг в друга блоки кода не накручивают стек? Ведь goto может прыгнуть, невзирая на них.
Я сто лет не использовал goto, на C#, вообще, ни разу. Могу и ошибаться в оценке.
RD>>1. На машинном уровне это одна инструкция прямой передачи управления, против раскрутки стека потока в случае с exception M>А вложенные друг в друга блоки кода не накручивают стек? Ведь goto может прыгнуть, невзирая на них. M>Я сто лет не использовал goto, на C#, вообще, ни разу. Могу и ошибаться в оценке.
Не совсем понял, что значит "накручивать" стек.
Я говорил о "раскрутке" стека.
Это когда при возникновении exception'a CLR идет вверх по стеку вызовов, пытаясь найти подходящий обработчик исключения.
В данном случае раскрутка будет неглубокой. Она остановится на уровне той же самой функции. Но это все равно более тяжеловесный механизм, чем прямая передача управления.
Если же под "накручивать стек" имелся ввиду рост размера стека при размещение в нем локальных переменных (счетчики циклов и т.п.),
то это будет происходить в любом случае (точнее в том случае, если компилятору не хватит регистров, чтобы разместить в них все локальные переменные метода).
Здравствуйте, RushDevion, Вы писали:
RD>Если же под "накручивать стек" имелся ввиду рост размера стека при размещение в нем локальных переменных (счетчики циклов и т.п.), RD>то это будет происходить в любом случае (точнее в том случае, если компилятору не хватит регистров, чтобы разместить в них все локальные переменные метода).
Да. я про этот случай.
Здравствуйте, #John, Вы писали:
J>какой код будет производительней/правильней писать(a именно в плане применять if или exception):
Это зависит не от кода, а от бизнес-логики. Простая арифметика не нуждается в исключениях. Но если в числодробилке неприемлемые условия — конечно кидать исключение.
Здравствуйте, #John, Вы писали:
J>Здравствуйте, J>какой код будет производительней/правильней писать(a именно в плане применять if или exception):
В плюсах я бы exception не использовал. Помимо просто рассуждений о control flow, можно terminate словить, если при раскрутке стека твоих вложенных циклов кто-то из деструкторов тоже кинет. В случае goto просто получишь исключение, которое можно поймать.
J>int i=0;
J>try{
J>do {
J> for(...)
J> for(...)
J> i++;
J> do smth...
J>} while (++i < length);
J>}
J>catch(Exception ex){ ... ignore ex ...}
J>exit:;
J>...
J>
Переписать алгоритм нормально, чтобы не городить goto, одинаковых проверок в цикле и вложенных циклов по одному и тому же i, который чёрт знает где и как внутри меняется?
Здравствуйте, andyp, Вы писали:
A>Здравствуйте, #John, Вы писали:
J>>Здравствуйте, J>>какой код будет производительней/правильней писать(a именно в плане применять if или exception):
A>В плюсах я бы exception не использовал. Помимо просто рассуждений о control flow, можно terminate словить, если при раскрутке стека твоих вложенных циклов кто-то из деструкторов тоже кинет. В случае goto просто получишь исключение, которое можно поймать.
Если я правильно помню, плюсы в принципе не любят деструкторов, которые могут кинуть исключение. Если кто-то пишет такие деструкторы, то он сам себе злобный буратино.
Здравствуйте, karbofos42, Вы писали:
K>Если я правильно помню, плюсы в принципе не любят деструкторов, которые могут кинуть исключение. Если кто-то пишет такие деструкторы, то он сам себе злобный буратино.
В общем случае да, именно по этой причине. Но иногда, чтобы за собой подчистить, требуется потенциально кидающая операция. А так, в современных плюсах есть проверки, есть ли исключение в полете, но иногда народ просто забывает, что что-то кидает.
Здравствуйте, #John, Вы писали: J>какой код будет производительней/правильней писать(a именно в плане применять if или exception):
1) По производительности лучше if чем исключение. Условный переход или раскрутка стека?
2) По правильному: где-то прочитал для c++, но и для net я думаю аналогично, что надо применять исключения только в том случае, когда вы враве ожидать корректных данных или результатов операции, но их не получили. Например, вы обращаетесь к вектору по индексу. Раз у вас есть индекс, то очевидно, что массив должен содержать нужное количество элементов. И если их там не оказалось, кидать исключение. Если же отсутствие элементов в массиве является нормальным, то тогда применять if.
В вашем же случае всё очевидно. Вы делаете цикл по i. Но и внутри цикла меняете i и оно может стать больше length. То что i может стать больше length нормальная ситуация для вашего алгоритма. И будет крайне расточительно кидать exception. Проще сделать break по условию, goto etc.
Здравствуйте, Sinatr, Вы писали:
S>В случае c# исключения прежде всего довольно "тяжеловесные".
Не такие уж они тяжеловесные, несколько миллионов исключений в секунду вполне успевают выбрасываться. А байки про невероятную тяжеловесность исключений вызваны наблюдением за программой под отладчиком, когда исключение вызывает прерывание выполнения и подъем отладчика.
S> Из-за использования try/catch может ухудшиться читаемость когда (особенно, если они вложенные или уже находятся внутри вложенного блока кода).
С точностю до наоборот. Исключения улучшают читаемость кода по сравнению с проверкой условия. А уж тем более улучшают по сравнению с goto.
Что никоим образом, конечно, не означает что исключения стоит использовать для чего либо кроме обработки исключительных ситуаций.