Использование Goto для улучшения принципа СУХОЙ и ясности кода: хорошая идея? - PullRequest
0 голосов
/ 03 декабря 2009

У меня есть некоторый код, который структурирован следующим образом:

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");

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

Ответы [ 9 ]

5 голосов
/ 03 декабря 2009

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

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

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

MessageBox.Show("some warning");
2 голосов
/ 03 декабря 2009

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

1 голос
/ 03 декабря 2009

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

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 голосов
/ 03 декабря 2009

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

0 голосов
/ 03 декабря 2009

Так как (начиная с FrameWork 1.1) логическое и "&&": "вычисляет только свой второй операнд, если необходимо."

Что не так с:

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

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

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

0 голосов
/ 03 декабря 2009

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

0 голосов
/ 03 декабря 2009

Исключения - это правильный способ обрабатывать ошибки в .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
}

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

0 голосов
/ 03 декабря 2009

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

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

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

if (!doSomething())
{
    showError();
}
doSomethingElse();
if (!anotherCall())
{
    showError();
}
0 голосов
/ 03 декабря 2009

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

...