6

goto の使用は、ほとんどの人が避けるように言っていることは知っていますが、単純なコードが必要な場合に便利な場合があることをさまざまな場所で読みました。現在、ユーザーが選択した場合に繰り返す必要がある非常に単純なプログラムがあります。

static void Main()
{
    Restart:
    ...

    string UserChoice=Console.ReadLine();
    if (UserChoice=="y")
    goto Restart;
}

ここで goto を使用するのは本当に悪いことですか? ループなどを行わずにコードを繰り返す方法は他にありません。これは非常に簡単でクリーンな方法のようです。または、何か不足していますか?

4

11 に答える 11

20
string userchoice;

do {                

    userchoice=Console.ReadLine();

} while (userchoice=="y");
于 2010-09-24T09:14:21.903 に答える
5

代わりに以下のように書きます。

while(Console.ReadLine() == "y")
{
.....
}

はい、コードが読みにくくなるため、goto を使用するのは良くありません。

于 2010-09-24T09:04:57.913 に答える
5

もちろん、コードで同じことを何度も行う場合は、ループを追加する必要があります。それは後藤よりもはるかに優れています。

このようなものを使用してください

string UserChoice = "y";
while( UserChoice == "y"){
  ...
  UserChoice=Console.ReadLine();
}

それはあなたにとってうまくいくはずです。

于 2010-09-24T09:05:21.267 に答える
4

ここで goto を使用するのは本当に悪いことですか?

1968 年 3 月、Dijkstraは ACM の Communications に手紙を送りました。これは興味深い読み物であり、プログラマーの伝承の一部です。

この手紙で提示された GOTO に対する反論は、プログラマーがコード実行の進行状況を追跡するためのメンタル モデルを構築する方法に関係しています。ダイクストラは、変数の値は実行の進行状況に関連してのみ意味を持つため、このようなメンタル モデルが重要であると主張しています。たとえば、プログラムがイベントの発生回数をカウントしている場合、N 個のイベントが発生する中間の瞬間が常にありますが、それを追跡する変数はまだインクリメントされておらず、N-1 のままです。

彼は、GOTO に反対する理由付けで次の手順を実行します。

  1. まず、プロシージャ、ループ、または GOTO を使用しない非常に単純な言語を考えてみましょう。このような言語では、プログラマーは、実行ポインターがファイルの先頭から末尾まで進むことを想像することで、頭の中で実行を追跡できます。モデルの実行の進行状況には、1 つのインデックス (つまり、行番号) で十分です。

  2. 次に、手続きを言語に追加します。実行の進行状況は、プロシージャ内にある可能性があるため、単一のインデックスでは追跡できなくなりました。また、プロシージャが呼び出された行を追跡する必要もあります。また、プロシージャは他のプロシージャから呼び出すことができます。したがって、実行の進行状況を一連のインデックスとしてモデル化します。(実際には、プログラマーはこのようなシーケンスを「スタック トレース」と呼んでいます。)

  3. 次に、言語にループを追加します。ループ本体内にあるスタック トレースの各行に対して、別のタイプのインデックスを追加して、実行の進行状況をモデル化する必要があります: 繰り返し回数です。

  4. 次に、GOTO を追加します。Dijkstra は、GOTO を無制限に使用すると、実行の進行状況を追跡する能力が低下すると主張しています。「現在、152 番目のステートメントを実行しています」と言うと、「実行クロック」で実行の進行状況を追跡できます。ただし、変数の値を解釈するために必要なコンテキストを確立するには、これはあまり役に立ちません。

GOTO 文だけを使って単純なループを構築する限り、状況は (3) と同等であり、問​​題はないと主張できます。ただし、その場合は、ループ構造を使用できます。ポイント(4)で説明されている状況に陥らないように、GOTOをコードから除外することをお勧めします。

于 2010-09-24T11:08:45.107 に答える
3

do/while ループを使用します。

string UserChoice = "";
do {
    ...
    UserChoice=Console.ReadLine();
} while(UserChoice == "y");
于 2010-09-24T09:06:02.700 に答える
2

答えに欠けている基本的な解決策が1つあります。

while (true)
{
    ...
    if (other-stop-condition) break;     

    ...

    string UserChoice=Console.ReadLine();
    if (UserChoice != "y") break;
}

このbreakステートメントは、純粋な while よりも構造化されていないが、(実際の) goto よりも構造化されていると見なされます。控えめに使用する必要がありますが、other-stop-condition

ここでgotoを使用するのは本当に悪いですか?

この単純なプログラムではありません。しかし、ループ、if/then などを置き換えるために使用し続けるとgoto、コードを回避するコードよりもはるかに速く複雑になりますgoto

于 2010-09-24T10:02:42.777 に答える
1

再帰関数を使用して、ループなしで同じことを行うことができます。

public static void Main(string[] args)
{
   PrintChoices();
}

private static void PrintChoices()
{
    string userChoice = Console.ReadLine();

    if (userChoice == "y")
        PrintChoices();        
}
于 2010-09-24T09:07:24.460 に答える
1

GOTO の代わりにメソッドを使用することは、より広く受け入れられています。

static void Main()
{
    Restart();
}

static void Restart()
{
    ...code

    string userChoice = Console.ReadLine();
    if (userChoice=="y")
        Restart();
}
于 2010-09-24T09:09:36.017 に答える
1

do while ループを使用して、goto をより読みやすいものに置き換えます。

do 
{
...
}
while(Console.ReadLine() == "y");
于 2010-09-24T09:13:48.583 に答える
0

個人的には、goto を使用する必要はありませんでした。Øyvind Bråthen と Numenor が述べたように、ループ メソッドはこのタスクを実行するための最良の方法です。

ただし、goto が役立つと思われるケースが 1 つあります。

スイッチの「フォール スルー」は 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; 
}
于 2010-09-24T09:12:01.203 に答える