コンパイラ最適化について勉強していました。
まず、C言語では、gccで以下のような記述ができます。
c
1void main() 2{ 3 int i = 1; 4 void *labels[2] = { &&LABEL0, &&LABEL1 }; 5 goto *labels[i]; 6LABEL0: 7 printf("LABEL0\n"); 8 goto END; 9LABEL1: 10 printf("LABEL1\n"); 11 goto END; 12END: 13 printf("END\n"); 14}
&&LABEL0というのは、gccの拡張文法です。
これは、labelが何十個と増えた場合に、if else文やswitch文より高速に動作するように思えます。
ここで、C#で上記と同様の内容を書くことはできないでしょうか?というのが質問です。すなわち、ラベルを値として扱えないか、ということです。
なお、以下は試してみましたがダメでした。
cs
1void main() 2{ 3 int i = 1; 4 switch (0) 5 { 6 case 0: goto case i+1; //定数値が必要です。 7 case 1: Console.WriteLine("i=0"); break; 8 case 2: Console.WriteLine("i=1"); break; 9 } 10}
また、そもそもこの質問がちんぷんかんぷんなことを言っていた場合、それも指摘くださると嬉しいです。
昔、避けるべきとよく言われていたスパゲッティプログラムを作るような気がします。保守性を考えて、普通に switch - case や if - else を使った方が良いのではないでしょうか?
本当にそれが高速動作するのかどうか計測してみてください。C 言語の switch を最適化を有効にしてコンパイルすると、ジャンプテーブルを作って同様のコードになるか、もしくは更に高速なものになるかもしれません。
C# では System.Reflection.Emit 名前空間のクラスやまたは System.Linq.Expressions 名前空間のクラスを使えばできなくはないのではないかと思いますが、デメリットの方が多すぎて無意味です。
今回の質問はアセンブリの勉強から出た発想であり、普段使いでgoto文を使用したことはないです。
ならば System.Linq.Expressions 名前空間のクラス群を学習されたらどうでしょうか。
自分で式木を組み立てるなら、ラベルを配列に入れることも、そこにジャンプすることもできるはずです。
組み上げた式木を Expression<Action>.Lambda に入れて Compile メソッドでコンパイルすると、通常のメソッドのようにデリゲートに入れて使うことができます。
できるはずと書きましたが、ちゃんと調べてないので本当にできるかどうかは知りません。これで無理なら System.Reflection.Emit 空間のクラス群を使って動的メソッドを生成すればできそうです。これもやったことはないので自分で確かめてください。
上はオブラートに被せてレスしましたが、はっきり言って、デメリットしかなくて、質問者さんが言われるように「ちんぷんかんぷん」な話と思います。
スパゲッティプログラムでググってみてください。
高速動作するのかどうか分かりませんが、もしそうだとしても、そこがアプリのボトルネックになっていて、絶対改善が必要という実務的な話ではないですよね?
> ここで、C#で上記と同様の内容を書くことはできないでしょうか?というのが質問です。
について、各回答者に見解の相違があるようです。
> すなわち、ラベルを値として扱えないか
ということですが、raccy さんが根拠を明確にされた通り、また質問者さんの確かめられた通り、C# の文法の範囲内ではラベルを値として使うことはできません。ここまでは大前提で、答えは No になります。
そこで私は、「C# で」を「C# の文法として」ではなく「C# を使用して」と読むなら「ラベルを値として扱うことができる」と示唆しています。これは「アセンブリの学習目的」という方針を根拠にしたものです。
y_waiwai さんの回答は、それは GCC 独自の拡張であって、C 言語でもできないし、可読性が落ちて危険性が増すのですべきではない、よって C# も同様であるというものです。SurferOnWww さんの意見も同主旨と感じています。
asm さんと catsforepaw さんの回答は、コンパイル後は同じものになるので switch を使うのが良いというものです。これは、
> これは、labelが何十個と増えた場合に、if else文やswitch文より高速に動作するように思えます。
に答えたものだと思います。
そして maisumakun さんの回答は、配列にデリゲートを入れるという、実務でもよく使われるテクニックについての言及です。これは主に分岐後の処理が動的なものである時、または非常に多く switch では可読性が落ちる時に使われる実用的なもので、質問の背景を想像して書かれたものではないかと思います。
質問に対する回答は全員「No」です。まだ解決しないのであれば、質問を編集し、どの部分をもっと深く知りたいのかを明確にしてください。
回答6件
あなたの回答
tips
プレビュー