連載:[完全版]究極のC#プログラミング

Appendix 1 Visual Studio 2005/2008のコンパイラの新機能

川俣 晶
2010/06/21
Page1 Page2

 本記事は、(株)技術評論社が発行する書籍『[完全版]究極のC#プログラミング ― 新スタイルによる実践的コーディング』から、許可を得て転載しています。
 同書籍は、もともと本フォーラムにて連載していた『C# 2.0入門』、『C# 3.0入門』の記事を整理統合し、加筆、修正されたものです。

  手元でまとめて読みたい方は、ぜひ書店などにてお買い求めください。

 【注意】本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどは@ITのそれとは一致しません。あらかじめご了承ください。

 厳密にはC# 3.0の機能ではないが、Visual Studio 2005/2008のC#コンパイラにもいくつか新機能が用意されている。また、削除された機能もあるので、以下に簡単にまとめる。

 これらはコンパイラをコマンドラインから起動するオプションとして指定できるほか、一部はVisual Studioからプロジェクトのプロパティとして変更できる。

A1.1 C# 2.0コンパイラでの変更点

■/errorreportオプション

 C#コンパイラがソースコードを処理できない場合に発生する内部コンパイラエラー(ICE:Internal Compiler Error)をマイクロソフトに報告する方法を指定する。

 このICEというのは、プログラマーがソースコードを書き間違ったことで発生するコンパイルエラーのことではなく、コンパイラ自身が処理を継続できない状態に陥ったことを示す。これは、コンパイラそのもののバグや言語仕様の不整合などによって発生するものだと思われる。C#は、言語仕様そのものがシンプルに単純化されていないので、このような問題が比較的起こりやすいのかもしれない。その場合の対処は、コンパイラの修正や言語仕様の修正であるので、対処はマイクロソフトにしかできない。そのため、エラーの報告をいかにしてマイクロソフトに送るか……という選択肢しか存在しない。

 このオプションで指定できる値は表A1.1の4種類である。

内容
none 送信しない
prompt 送信するか否かを問い合わせる(IDEでは既定)
queue エラーレポートをキューにためておき、管理者権限を使ってログオンしたときに、3日に一度の頻度で送信を問い合わせる(コマンドラインでは既定)
send 自動送信する
表A1.1 /errorreportオプションで指定できる値

 Visual Studio上で、プロジェクトのプロパティを使って設定を変更するには[ビルド]タブの[詳細設定]ボタン →[内部コンパイルエラー報告]ドロップダウンを使用する。

 以上、詳しく説明したが、このようなエラーに遭遇する頻度は決して高いものではない。筆者も、かなりC#のソースを書いたが、遭遇したという明瞭な記憶はない。遭遇するまで忘れていてもかまわない機能だろう。

■/incrementalオプションの削除

 旧版C#コンパイラには、変更箇所だけをコンパイルするインクリメンタルコンパイル機能のオン/オフを指定する「/incremental」オプションがあった。これは削除された。

■/keycontainerオプションと/keyfileオプション

 「/keycontainer」オプションは、暗号化キーコンテナの名前を指定する。コンパイラは、指定されたコンテナに格納された公開キーをアセンブリのマニフェストに追加し、最終的なアセンブリを秘密キーで署名することによって、共有可能なコンポーネントを生成する。

 「/target:module」を使用してコンパイルすると、キーファイル名はモジュールに保持され、「/addmodule」オプションを使用してこのモジュールをコンパイルするときに作成されるアセンブリに組み込まれる。

 このオプションに相当する方法は、任意のソースコード上でカスタム属性(System.Reflection名前空間のAssemblyKeyName属性)として指定することもできる。Visual Studioのプロジェクトのプロパティから指定することはできない。

 一方、「/keyfile」オプションは、暗号化キーの格納されたファイル名を指定する。このオプションを使用すると、コンパイラによって指定したファイルに格納されている公開キーがアセンブリマニフェストに対して追加され、最終的なアセンブリが秘密キーで署名される。

 Visual Studio上で、プロジェクトのプロパティを使って設定を変更するには、[署名]タブの[アセンブリの署名]チェックボックスと[厳密な名前のキーファイルを選択してください]ドロップダウンを使用する。

■/langversionオプション

 受け付ける言語仕様の範囲を変更する。指定可能な値は、次ページ表A1.2の3種類となる。

内容
ISO-1 コンパイラはISO/IEC 23270:2003 C#の言語仕様に含まれていない構文に対してエラーを生成する
ISO-2 コンパイラはISO/IEC 23270:2006 C#の言語仕様に含まれていない構文に対してエラーを生成する
default コンパイラは有効なすべての構文を受け入れる。既定値は/langversion:defaultである
表A1.2/langversionオプションで指定できる値

 このような機能からわかるとおり、この「/langversion」オプションはC# 3.0コンパイラをC# 1.xコンパイラとして使用するような用途を想定したものではなく、国際規格であるISO/IEC規格に適合するソースコードを利用するための機能と考えるべきだろう。

 Visual Studio上で、プロジェクトのプロパティを使って設定を変更するには[ビルド]タブの[詳細設定]ボタン →[言語バージョン]ドロップダウンを使用する。なお、ISO/IEC 23270:2003はC# 1.xに、ISO/IEC 23270:2006はC# 2.0にほぼ対応する。

■/linkresourceオプション

 C# 1.x時代から存在するオプションだが、リソースのアクセシビリティを指定する機能が追加されている。次のように、リソースファイル名、リソースの論理名の後にカンマで区切って「public」または「private」を記述してアクセシビリティを指定できる。

/linkresource:ファイル名[,識別子]
/linkresource:ファイル名[,識別子[,アクセス修飾子]]

 ちなみに、既定値は「public」となる。Visual Studioのプロジェクトのプロパティで指定することはできない。

■/moduleassemblynameオプション

 モジュールを作成する際、外部のアセンブリからフレンドアセンブリ(第11章参照)として参照される名前を指定する。ただし、このオプションはフレンドアセンブリの機能を使用するために必須というわけではない。

 このオプションを正しく理解するには、.NET Frameworkの世界において、アセンブリとモジュールは別個の存在であることを把握しなければならない。アセンブリは通常「.exe」や「.dll」の拡張子を持っているが、モジュールは「.netmodule」という長い拡張子を持つ。そして、モジュールはアセンブリの構成要素として取り込むことができる。C#コンパイラは、「/target:module」を指定することで、モジュールを作成することができ、そのモジュールは「/addmodule:ファイル名」というオプション指定によって、アセンブリに取り込むことができる。

この機能性はフレンドアセンブリとモジュールの作成に決定的な問題を生じさせる。なぜかといえば、第11章p.178「フレンドアセンブリの使い方」で解説したInternals

 VisibleTo属性は、アセンブリの名前を指定するにもかかわらず、モジュール単位でコンパイルする場合、コンパイル時にアセンブリの名前が確定できないからである。アセンブリの名前が決まっていなければ、いくらInternalsVisibleTo属性でアセンブリの名前を指定しても、許可が成立しない。

 そこで、このオプションを使用して「そのモジュールが将来属するはずのアセンブリの名前」を指定するわけである。これによって、モジュール単位でコンパイルする場合にも、フレンドアセンブリの機能を利用することが可能となる。

 なお、これに相当する機能はVisual Studioのプロジェクトのプロパティで指定することはできないが、そもそも、Visual Studioではモジュール単位でコンパイルを行わない(行えない)ので、特に問題はないだろう。

■/pdbオプション

 デバッグ情報ファイル(拡張子「.pdb」)は、通常、出力ファイル(.exeファイルまたは.dllファイル)が作成されるのと同じディレクトリに、出力ファイルと同じ名前で作成される。このオプションはそれを任意のパスに変更する。

 Visual Studioのプロジェクトのプロパティで指定することはできない。

■/platformオプション

 プログラムの実行対象となるプラットフォームを指定する。値としてはx86、Itanium、x64、anycpuを指定でき、anycpuが既定値となる。

 本来、仮想マシン語の一種であるCILの世界では、CPUの種類は関係がないはずである。しかし、32ビット版のCLRと64ビット版のCLRでは確保できる最大メモリが異なったり、参照のために消費するメモリ容量が異なったりするなど、実行環境の相違がプログラムの実行に影響を及ぼすことも考えられる。

 このことは、特に64ビット環境で顕著な問題となる。なぜなら、64ビット環境の上では、プログラムを64ビット版CLRとWOW64*1環境の32ビット版CLRの双方で実行できる可能性があるためである。

 このような状況では、「/platform」オプションを使用することで、ある程度どのCLRで実行されるかを指定することができる。

 次は、「/platform」オプションのドキュメントに記述された実行環境の選択条件である。

  • x86を指定すると、32ビットのx86互換共通言語ランタイムで実行されるアセンブリがコンパイルされます。
  • Itaniumを指定すると、Itaniumプロセッサ搭載コンピュータ上の64ビット共通言語ランタイムで実行されるアセンブリがコンパイルされます。
  • x64を指定すると、AMD64またはEM64T命令セットをサポートするコンピュータ上の64ビット共通言語ランタイムで実行されるアセンブリがコンパイルされます。
  • anycpu(既定値)を指定すると、任意のプラットフォームで実行されるアセンブリがコンパイルされます。

 さらに、64ビットのWindowsオペレーティングシステムでは次のようになるとされる。

  • /platform:x86を指定してコンパイルしたアセンブリは、WOW64環境の32ビットCLR上で実行されます。
  • /platform:anycpuを指定してコンパイルした実行可能ファイルは、64ビットCLR上で実行されます。
  • /platform:anycpuを指定してコンパイルしたDLLは、読み込み先のプロセスと同じCLR上で実行されます。

 Visual Studio上で、プロジェクトのプロパティを使って設定を変更するには[ビルド]タブの[プラットフォームターゲット]ドロップダウンを使用する。ただし、Express Editionではこの機能は使用できない。

*1 WOW64は、Windows on Windows 64の略で、64ビット版のWindowsで32ビット版のアプリケーションをそのまま動作させるための仕組みを指す。

A1.2 C# 3.0コンパイラ用の機能

■/win32Manifest

 実行可能ファイルに埋め込むユーザー定義のWin32アプリケーションマニフェストファイルを指定する。たとえば、Windows Vistaで管理者権限を要するプログラムは、この機能でrequireAdministratorの要求実行レベルを指定したカスタムマニフェストを指定できる(Visual Studioでは、プロジェクトのプロパティでも指定できる)。

■/noWin32Manifest

 マニフェストの埋め込みを行わないことを指定する。これを使用すると、(別の経路で指定されない限り)Windows Vista上では仮想化されて実行されることを意味する(Visual Studioでは、プロジェクトのプロパティでも指定できる)。

 これらは、C# 3.0のための機能というよりも、Windows Vistaのための機能といえる。しかし、これらの機能が具体的に何を実現するかは、もしかしたら直感的にわかりにくいかもしれない。というのは、そもそも、UAC(ユーザーアカウント制御)に対する具体的な知識が驚くほど世の中に普及していないようであるからだ。

 たとえば、Vistaでは動かないソフトが多すぎるといった批判が“誰もが承認した常識的事実”として語られる機会は多いが、筆者の過去の経験からいえば、Vistaで動かないソフトは一般のアプリケーションに限ればほんの一握りでしかない。単に立ち上げるだけでは動かないソフトは珍しくもないが、それはUACによって動作がブロックされているだけの話であり、適切な権限で動作するように設定すればたいてい動く。そして、安全なOSを求めるユーザーの大合唱に応えるために導入されたのがUACである以上、いまさらUAC抜きの世界には戻れない。

 それにもかかわらず、安全なOSをよこせと要求したユーザーたちが、自分たちの安全を実現するために用意されたUACの機能を理解できず、危険性の高いWindows XPをいつまでも使い続けようとする態度はよく見られる。これは、安全のための歩道橋を作れと要求しながら、いざ歩道橋ができると階段が面倒なので道路を直接突っ切るような態度と同様といえる。それは、決して賢い態度ではない。

 これらのコンパイラスイッチは、そのような意味で賢くあろうとする開発者のためのものだといえる。もはやUACのない世界に戻るという選択肢がほとんどありえない以上、このような機能をマスターしてすばらしいプログラムを世に送り出そう。


 INDEX
  [完全版]究極のC#プログラミング
  Appendixes コンパイラ新機能/式ツリー
  1.Appendix 1 Visual Studio 2005/2008のコンパイラの新機能
    2.Appendix 2 .NET Framework 3.5の新機能 − 式ツリー

インデックス・ページヘ  「[完全版]究極のC#プログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間