C# goto use-что еще использовать здесь?
Я знаю, что использование goto-это то, что большинство людей говорят, чтобы избежать, однако я читал в разных местах, что иногда полезно, если вам нужен простой код. В настоящее время у меня очень простая программа, которую нужно повторить, если пользователь выбирает так:
static void Main()
{
Restart:
...
string UserChoice=Console.ReadLine();
if (UserChoice=="y")
goto Restart;
}
использование goto здесь действительно так плохо? Я просто не вижу другого способа повторить код без выполнения циклов и т. д. Это кажется очень простым и чистым способом. Или я что-то упускаю?
11 ответов
вместо этого напишите что-то вроде ниже.
while(Console.ReadLine() == "y")
{
.....
}
Да использование goto-это плохо, потому что это делает ваш код менее читабельным.
конечно, если ваш код будет делать то же самое снова и снова, вам нужно добавить петли. Это намного лучше, чем Гото.
использовать что-то вроде этого
string UserChoice = "y";
while( UserChoice == "y"){
...
UserChoice=Console.ReadLine();
}
Это должно хорошо сработать для вас.
использование goto здесь действительно так плохо?
В Марте 1968 Года, Дейкстра направлено письмо связь ACM, который был опубликован под названием Перейти К Заявлению Считается Вредным. Это интересное чтение и часть знаний программиста.
аргумент против GOTO, представленный в этом письме, связан с тем, как программисты строят ментальную модель для отслеживания хода выполнения кода. Дейкстра утверждает, что такая ментальная модель важна, поскольку значение переменных имеет смысл только относительно хода выполнения. Например, когда наша программа подсчитывает количество раз, когда происходит событие, всегда есть промежуточный момент, когда произошло N событий, но переменная, отслеживающая его, еще не была увеличена и все еще находится на N-1.
Он проходит через эти шаги в своих рассуждениях против Гото:
сначала рассмотрим очень простой язык без процедур, циклов или GOTO. На таком языке программист может мысленно отслеживать выполнение, представляя указатель выполнения, идущий от начала файла до конца. Для моделирования хода выполнения достаточно одного индекса (т. е. номера строки).
теперь мы добавляем процедуры к языку. Ход выполнения больше не может отслеживаться одним индексом, так как он может находиться внутри процедуры. Мы также должны отслеживать, с какой линии процедура была вызвана. Кроме того, процедуры могут быть вызваны из других процедур. Поэтому мы моделируем ход выполнения как последовательность индексов. (В реальной жизни программисты называют такую последовательность "трассировкой стека".)
теперь мы добавляем циклы к языку. Для каждой строки в нашей трассировке стека, которая находится внутри тела цикла, нам нужно добавить другой тип индекса для выполнения модели: количество повторений.
теперь добавим GOTO. Дийкстра утверждает, что с необузданным использованием GOTO наша способность отслеживать прогресс выполнения теперь ломается. Мы все еще можем отслеживать ход выполнения с помощью "часов выполнения", говоря:"теперь мы выполняем 152-й оператор". Однако это не очень полезно для установления контекста, необходимого для интерпретации значений переменных.
пока мы используем только операторы GOTO для построения простых циклов, вы можете утверждать, что ситуация эквивалентна точке (3), и нет проблема. Но в этом случае вы можете просто использовать конструкции петли. Лучше просто держать GOTO вне вашего кода, чтобы вы не проскользнули в ситуацию, описанную в пункте (4).
Я бы использовал цикл do/while:
string UserChoice = "";
do {
...
UserChoice=Console.ReadLine();
} while(UserChoice == "y");
вы можете использовать рекурсивную функцию, чтобы сделать то же самое без циклов:
public static void Main(string[] args)
{
PrintChoices();
}
private static void PrintChoices()
{
string userChoice = Console.ReadLine();
if (userChoice == "y")
PrintChoices();
}
использование методов вместо GOTOs более широко принято:
static void Main()
{
Restart();
}
static void Restart()
{
...code
string userChoice = Console.ReadLine();
if (userChoice=="y")
Restart();
}
в ответах отсутствует одно основное решение,
while (true)
{
...
if (other-stop-condition) break;
...
string UserChoice=Console.ReadLine();
if (UserChoice != "y") break;
}
на break
оператор считается менее структурированным, чем чистый while, но более структурированным, чем (реальный) goto. Он должен использоваться экономно, но у него есть свои применения, как с other-stop-condition
использование goto здесь действительно так плохо?
не в этой простой программе. Но если вы продолжаете использовать goto
для замены циклов, если / то etc ваш код увеличится в сложность намного быстрее, чем код, который позволяет избежать goto
.
используйте цикл do while для замены вашего goto как более читаемого.
do
{
...
}
while(Console.ReadLine() == "y");
лично мне никогда не приходилось использовать goto, и, как Øyvind Bråthen и Numenor заявили, что метод loop является лучшим способом выполнения этой задачи.
однако есть один случай, когда я могу думать о том, где goto будет полезно
как переключатель "провалиться" является незаконным в C# (вызывает ошибку компилятора):
switch (a)
{
case 3:
b = 7;
case 4:
c = 3;
break;
default:
b = 2;
c = 4;
break;
}
чтобы заставить его работать, вы можете использовать goto:
switch (a)
{
case 3:
b = 7;
goto case 4;
case 4:
c = 3;
break;
default:
b = 2;
c = 4;
break;
}
class Program
{
static void Main(string[] args)
{
int add;
try
{
ArrayList al = new ArrayList();
t:
Console.Write("Enter the Number of elements do you want to insert in arraylist");
int n = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Enter the Values:");
for (int i = 0; i < n; i++)
{
al.Add(Console.ReadLine());
}
foreach (var a in al)
{
Console.WriteLine("valus:" + a);
}
Console.WriteLine("Add another number yes:1 ");
add = Convert.ToInt32(Console.ReadLine());
while (add == 1)
{
goto t;
}
}
catch (Exception ex)
{
Console.WriteLine("Enter the Valid Number and try again");
}
Console.ReadKey();
}
}
}