http://f57.aaa.livedoor.jp/~jeanne/bbs/faq.cgi?mode=al2&namber=5089
「ほぼ」一緒のはずだ。同じ処理をするコードを書いたら、C# コンパイラと VB コンパイラは同じ IL を出力する。
「ほぼ」同じとは歯切れが悪い。全く一緒ではないのか?
Visual Studio 2005、つまり C#2.0 と VB8 で検証してみる。
C#
static void Main()
{
int i = 32768;
short s = (short)i;
}
VB
Sub Main()
Dim i As Integer = 32768
Dim s As Short = CShoft(i)
End Sub
上のような単純なコードにも違いはある。何が違うのだろうか。実行してみれば一目瞭然である。VB の方は「OverflowException」がスローされる。
IL レベルで検証してみよう。
C# IL
.method private hidebysig static void Main() cil managed
{
.entrypoint
// コード サイズ 11 (0xb)
.maxstack 1
.locals init ([0] int32 i,
[1] int16 s)
IL_0000: nop
IL_0001: ldc.i4 0x8000
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: conv.i2
IL_0009: stloc.1
IL_000a: ret
} // end of method Program::Main
VB IL
.method public static void Main() cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// コード サイズ 12 (0xc)
.maxstack 1
.locals init ([0] int32 i,
[1] int16 s)
IL_0000: nop
IL_0001: ldc.i4 0x8000
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: conv.ovf.i2
IL_0009: stloc.1
IL_000a: nop
IL_000b: ret
} // end of method Module1::Main
IL での違いは、conv.i2 と conv.ovf.i2 だ。(他にも細かい違いはあるが処理速度には無関係)
これら命令が行う処理は「評価スタックの一番上の値を Int16 に変換し、Int32 への拡張 (埋め込み) を行います」だ。分かりにくいが要は Int16 に変換だ。conv.ovf.i2 の方はこれに加えてオーバーフローチェックを行ってくれる。
どちらが速いか遅いかは分からないが(もっと詳細に書いている文書があるはずだが)、どう考えても conv.ovf.i2 の方が余分に処理をしている。つまり、全く同じ処理を書いても C# より VB の方が遅い IL を吐き出している。
しかし、これはコンパイラの設定を Visual Studio 2005 の規定のままにした時の挙動である。C# コンパイラに「/checked」オプションを付けてコンパイルすると、VB 同様オーバーフローチェックを行う IL を吐き出す。
C# と VB で完全に同じ処理をするコードを書いたら完全に同じ IL になるが、完全に同じ処理を書いているように見えるのは、あくまで表面的にである。今回のような単純な処理でも「完全に同じ処理」ではないのだ。
これ以外にも、VB は遅延バインディングを容易に行うことができ、そうなると IL には見た目以上に余分な処理が入る。
「では結局 VB より C# の方が速いのか?」という結論は早計だ。
確かにデフォルトでは C# コンパイラは VB コンパイラより軽量な IL を出力するかもしれない。今回は C# 寄りな例を挙げただけで、私が知らないだけで、VB の方が軽量な IL を出力する例もあるかもしれない。しかし結局のところ、そういう事があっても劇的な速度の違いはないだろう。
結論。
C# と VB で完全に同じ処理をするコードを書けば、完全に同じ速度になる。
しかし、完全に同じ処理をするコードを書くという事はそう容易ではない。
処理速度に違いはあっても微々たる物だ。