2

goto が悪い設計手法であることはわかっています。しかし、ツールボックスに goto と if しかなく、無人島で立ち往生していると想像してください。そうではないでしょう:

    int i = 0;
    while (i < 10) i++; 

これと同一であること:

    int i = 0;
    loop: if (i < 10) { i++; goto loop; }

?

条件付きロジック、変数の割り当て/変更、メソッド呼び出し、ジャンプを使用するだけで、通常 c# でできることは何でもできるというのは本当ではないでしょうか?

4

4 に答える 4

4

技術的に?そのとおり。Goto プログラムは完全にチューリングされているため、すべてをそれらとして表すことができます。結局のところ、機械語は goto プログラムによく似ています。ループや処理はすべて条件付きジャンプを使用して行われるからです。もちろん、.NET ではgotoだけを使用することはできません。ある時点で、そのように書かれていない他のコードを使用する場所に出くわしたり、言語構造が他のことを強制する場所にいる (クラス、メソッド、関数などを作成する)。しかし、技術的には、はい。

しかし、あなたはそれをするべきですか?絶対違う。Goto プログラムは保守が非常に難しく、C# は中間言語にコンパイルされます。中間言語はジャンプを使用しますが、より高いレベルで使用されるため、これを行うとパフォーマンスが大幅に低下する可能性があります。また、仮想マシンは、「通常の」コードで多くの最適化を行うことができますが、それを固定の goto スキーマに配置した場合にはできません。

ところで。元のコードはこの IL にコンパイルされます。これは、基本的に goto を使用して記述したものです (私による注釈)。

// i = 0
IL_0001: ldc.i4.0                  // Load integer value 0 to stack
IL_0002: stloc.0   // i            // Store stack value in local variable 0

// goto loop-condition
IL_0003: br.s      IL_0009         // Jump to IL_0009

// loop-start:
// i = i + 1
IL_0005: ldloc.0   // i            // Load variable 0 to stack
IL_0006: ldc.i4.1                  // Load integer `1` to stack
IL_0007: add                       // Add top two stack values
IL_0008: stloc.0   // i            // Store result in local variable 0

// loop-condition:
// if (i < 10) { goto loop-start }
IL_0009: ldloc.0   // i            // Load variable 0 to stack
IL_000A: ldc.i4.s  0A              // Load integer `10` to stack
IL_000C: clt                       // Compare top two stack values
IL_000E: stloc.1   // CS$4$0000    // Store stack value in local variable 1
IL_000F: ldloc.1   // CS$4$0000    // Load variable 1 to stack
IL_0010: brtrue.s  IL_0005         // Jump to IL_0005 if stack value is true
于 2013-09-29T00:27:51.480 に答える
4

について必ずしも本質的に悪いことは何もありませんgoto。使用しないようにする理由は次のとおりです。

  • 非常に悪用しやすく、適切に使用するには細心の注意が必要です。それでも、コードが読みにくくなる傾向があります

  • whiledoforまたは_ _foreach

他のものを使用することは常に可能であり、常により優れているため、 を実際に使用することは決してありませんgoto

私が聞いた唯一の例外は、深いネスティングから抜け出すことです。

for (int x = 0; x < 100; x++)
   for (int y = 0; y < 100; y++)
      for (int z = 0; z < 100; z++)
         if (condition)
            goto end;
end: ;

VS

for (int x = 0; x < 100, !condition; x++)
   for (int y = 0; y < 100, !condition; y++)
      for (int z = 0; z < 100, !condition; z++)

そして、あなたの質問にもっと直接的に答えるために、はい、すべての制御フローをs 、 s などgotoではなく s で行うことは完全に可能です...それは実際のコードではなく、練習には良い挑戦になるとさえ提案するかもしれません。強制的に s を使用するよりも、アセンブリでコーディングしてみる方が、おそらくより良い学習体験になるでしょう。whiledogoto

于 2013-09-29T00:42:51.793 に答える
4

はい、ループを使用せずに同じ出力が得られるようにプログラムを書き直すことができます。メソッド呼び出しはすべてインライン化できるため、技術的にはそれらも必要ありません。もちろん、クラスやインターフェースもロジックにとって必須ではありません。実際、if、goto、代入、および加算を使用して、ほぼすべてのことを行うことができます。そんなに必要ないのかもしれません。

于 2013-09-29T00:24:21.763 に答える
1

はい、可能です。最終的には、アセンブリがどのように機能するかです。アセンブリにループなどはありません。コード内の場所を変更するには、"goto" (通常jmpまたは何らかの形式の "branch") または関数呼び出し (存在する場合) に相当するものを使用する必要があります。

ただし、継承したコード ベースがgotos を使用している場合は、最初から書き直すか、許可されていない場合は終了します。

于 2013-09-29T00:27:36.600 に答える