Заявления и альтернативы GoTo в VB.NET - PullRequest
9 голосов
/ 23 апреля 2010

Я разместил фрагмент кода на другом форуме с просьбой о помощи, и люди указали мне, что использование GoTo операторов - очень плохая практика программирования. Мне интересно: почему это плохо?

Какие альтернативы GoTo можно использовать в VB.NET, что, как правило, считается более эффективной практикой?

Рассмотрите этот фрагмент ниже, где пользователь должен ввести свою дату рождения. Если месяц / дата / год недействительны или нереальны, я хотел бы вернуться назад и спросить пользователя снова. (Я использую операторы if, чтобы проверить размер целого числа ... если есть лучший способ сделать это, я был бы признателен, если бы вы также сказали мне это: D)

retryday:
    Console.WriteLine("Please enter the day you were born : ")
    day = Console.ReadLine
    If day > 31 Or day < 1 Then
        Console.WriteLine("Please enter a valid day")
        GoTo retryday
    End If

Ответы [ 14 ]

18 голосов
/ 23 апреля 2010

Я собираюсь отличаться от всех остальных и сказать, что сами GOTO - не все зло. Зло исходит от неправильного использования GOTO.

В целом, почти всегда есть лучшие решения, чем использование GOTO, но действительно есть моменты, когда GOTO - это правильный способ сделать это.

При этом вы - новичок, поэтому вам нельзя позволять судить о том, является ли GOTO правильным или нет (потому что вряд ли когда-нибудь) в течение еще нескольких лет.

Я бы написал ваш код так (мой VB немного ржавый ...):

Dim valid As Boolean = False

While Not valid
    Console.WriteLine("Please enter the day you were born: ")

    Dim day As String

    day = Console.ReadLine

    If day > 31 Or day < 1 Then
        Console.WriteLine("Please enter a valid day.")
    Else
        valid = True
    End If
End While

Если вы возьмете свой код GOTO и посмотрите на него, как кто-то сначала подойдет к вашему коду? «Хм… повторный день? Что это делает? Когда это происходит? О, так мы переходим на этот ярлык, если день выходит за пределы диапазона. Хорошо, поэтому мы хотим выполнить цикл, пока дата не будет считаться действительной и находящейся в диапазоне» .

Принимая во внимание, что если вы посмотрите на мою:

«О, мы хотим продолжать делать это до тех пор, пока оно не будет действительным. Оно действительно, когда дата находится в пределах диапазона».

6 голосов
/ 23 апреля 2010

http://xkcd.com/292/ я думаю, что это стандартное мнение Гото.

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

Sub Main()
    Dim valid as Integer
    valid=0
    Do Until valid = 1
    System.Console.WriteLine("enter the day ")
    day = System.Console.ReadLine()
    If day > 31 Or day < 1 Then
       System.Console.WriteLine("Invalid day\n")
       valid = 0;
    Else
       valid = 1

    Loop

End Sub
2 голосов
/ 23 апреля 2010

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

Что касается альтернативы GoTo, в предоставленном фрагменте цикл while хорошо бы справился, возможно что-то вроде:

day = -1
While (day < 0)
   Console.WriteLine("Please enter the day you were born : ")
   day = Console.ReadLine
   If day > 31 Or day < 1 Then
     Console.WriteLine("Please enter a valid day")
      day = -1
   End If
End While
2 голосов
/ 23 апреля 2010

Конструкция GOTO создает код sphagetti. Это делает отслеживание кода практически невозможным.

Процедурное / функциональное программирование - намного лучший подход.

1 голос
/ 25 сентября 2012

Функции FTW!

Хорошо, я не уверен, что ваш код действительно VB.Net здесь, так как у вас есть что-то типа шаткого типа (т.е. Console.Readline возвращает String, а не число, с которым вы можете сравнивать ) ... поэтому на данный момент мы просто забудем о типе.

Console.Writeline("Please enter the day you were born : ")
day = Console.Readline()

While not ValidDate(day)
   Console.WriteLine("Please enter a valid day")
   day = Console.Readline()
End While

и отдельно

Function ValidDate(day) As Boolean
  Return day > 31 Or day < 1
End Function

Или вы можете повеселиться с рекурсией и синтаксисом с ранним возвратом! ;)

Function GetDate() As String
  Console.Writeline("Please enter the day you were born : ")
  day = Console.Readline()

  If ValidDate(day) Then Return day 'Early return

  Console.Writeline("Invalid date... try again")
  GetDate()
End Function
1 голос
/ 24 апреля 2010

Использование goto считалось плохой практикой на протяжении десятилетий. Возможно, это была обратная реакция против оригинального бейсика (до Visual Basic). В исходном BASIC не было циклов while, локальных переменных (только глобальных) и функций (в большинстве версий BASIC), которые не могли принимать параметры или возвращать значения. Кроме того, функции не были явно разделены; контроль может неявно переходить из одной функции в другую, если вы забыли инструкцию RETURN. Наконец, отступ в коде был чужой концепцией в этих ранних Бейсиках.

Если бы вы использовали оригинальный BASIC в течение некоторого времени (как я это делал), вы бы оценили, как использование глобальных переменных и gotos повсеместно делает большую программу трудной для понимания и без особой тщательности превратило ее в запутанный беспорядок "спагетти". Когда я изучал QBASIC с его циклами WHILE..WEND и SUB, я никогда не оглядывался назад.

Я не думаю, что gotos ранит в небольших количествах, но в культуре кодеров сохраняется сильное чувство, что они как-то злые. Поэтому я бы избегал gotos ни по какой другой причине, кроме как избежать оскорбительных чувств. Иногда я нахожу, что goto решает проблему чисто (например, разрыв внешнего цикла из внутреннего цикла), но вы должны подумать, не делает ли другое решение код более читабельным (например, поместите внешний цикл в отдельную функцию и используйте " функция выхода "вместо goto, во внутреннем цикле).

Я написал программу на C ++ с примерно 100 000 строк кода и использовал goto 30 раз. Между тем, существует более 1000 «нормальных» циклов и около 10 000 операторов «if».

1 голос
/ 23 апреля 2010

Немного неуклюже, но:

    Dim bContinue As Boolean

    Console.WriteLine("Enter a number between 1 and 31")

    Do
        Dim number As Integer = Console.ReadLine()
        If number >= 1 AndAlso number <= 31 Then
            bContinue = True
        Else
            Console.WriteLine("Please enter a VALID number between 1 and 31")
        End If
    Loop Until bContinue

Также рассмотрим некоторые базовые циклы в "Goto Land"

        Dim i As Integer
startofloop1:

        Debug.WriteLine(i)
        i += 1
        If i <= 10 Then
            GoTo startofloop1
        End If

        i = 0

startofloop2:

        Debug.WriteLine(i * 2)
        i += 1
        If i <= 10 Then
            GoTo startofloop2
        End If

Вот хороший эквивалент:

   For x As Integer = 0 To 10
        Debug.WriteLine(i)
    Next
    For x As Integer = 0 To 10
        Debug.WriteLine(i * 2)
    Next

Что является более читабельным и менее подвержено ошибкам?

1 голос
/ 23 апреля 2010

GOTO - довольно политический вопрос. «Решением» для GOTO является использование других встроенных навигационных конструкций, таких как функции, методы, циклы и т. Д. Для VB вы можете создать подпроцедуру, запускающую этот код, или поместить ее в цикл While. Вы можете легко погуглить обе эти темы.

0 голосов
/ 09 мая 2016

Я должен согласиться со всеми здесь: само GOTO не является злом, но неправильное использование этого, несомненно, сделает вашу жизнь несчастной. Есть так много других управляющих структур на выбор, и хорошо написанная программа может обрабатывать большинство ситуаций без goto. При этом я нахожусь на стадии завершения программы, которая занимает около 15 000 строк, и я использовал одну и только одну инструкцию GOTO (которую я, возможно, заменю, мы увидим). Впервые я использовал GOTO в последней дюжине программ, с которыми я имел дело. Но в этом случае он избавился от ошибки компилятора (используя Me.Close () дважды в одном и том же Sub, но в разных структурах If; я мог бы его подавить, но я просто добавил метку и заменил один Me.Close () на GoTo CloseLabel). Если я начну работать с большим количеством экземпляров, которым требуется Me.Close () в этом Sub, я, скорее всего, помещу Me.Close () в свой собственный sub и просто вызову этот sub из структур If или других циклов, которые приводят к закрытию программы ... Как я уже сказал, есть альтернативы, но иногда, и когда используются очень редко, экономно и стратегически, GoTo все еще может быть полезным. Просто остерегайтесь кода спагетти, это мерцающий беспорядок lol

0 голосов
/ 16 октября 2014
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...