もっとも重要なのは、まったく同じ手順の2つのプログラムを.NET Frameworkでコンパイルした場合と、.NET Framework以前の方法(例えば、従来のC++言語コンパイラ)でコンパイルした場合、この2つのモジュールは性質のまったく異なったモジュールになるという所です。
.NET以前の方法で構築(コンパイル)した場合には、そのマシンのCPUが読み込める機械語の形式に翻訳されたネイティブなモジュールになります。すなわち、CPUのアーキテクチャが異なる別のハードウェア上で動作させることは、一般的にはできません。OSが提供するAPIを使用している場合には、OSの種類やバージョンにも大きく影響を受けることになります。
一方、.NET Frameworkで動作するモジュールは、.NET Frameworkすべてに組み込まれているCLR(Common Language Runtime)と呼ばれるプログラムが読み込めるPEファイル(ポータブル実行ファイル)と呼ばれる形式のファイルで構成されるモジュールになっています(以降の記述では、この論理的なモジュールのことを「アセンブリ」と呼びます)。
このファイルは、上述のようなOSやデバイス(CPUなど)に固有な翻訳はされておらず、コンパイルしたPEファイルには、プログラマが記述したプログラムそのものに近い形のコードが独自のフォーマットで組み込まれており、CLRはこのコードを読み込んで実行するといったように動作します(注2)。
図2:.NET Frameworkの動作の仕組み (画像をクリックすると別ウィンドウに拡大図を表示します)
※注2:
実際には、IL(中間言語)に記述された処理は、インタプリタ方式で読み込んで動作するのではなく、パフォーマンスを考慮して、実行時にJIT(Just-In-Time)コンパイラと呼ばれるものを使用して、ネイティブモジュールをメモリ上に配置してから、動作しています。
ガベージコレクトや型チェックなどの仕組みなど、.NET Frameworkで開発されたプログラムのパフォーマンスは、C言語などを使ってネイティブ向けに作成されたものより劣りますが、このように可能な限り大きなパフォーマンスの差がでないよう設計されています。
すなわち、CLRを含む.NET Frameworkの実行環境が動作している環境であれば、OSに関係なく、またそれがパソコン以外のデバイスなどであろうとも同様に実行されることになります(注3)。
※注3:
正確には、パフォーマンスを向上させたい場合などに備え、PEファイルにネイティブコード生成用のコマンドを実行して、プラットフォームに依存したモジュールとして構築することもできます。ただしこの場合でも、IL(中間言語)で記述された部分は保持されており、別のプラットフォーム上に配置した場合には、このILを使って再コンパイルされます。
|