連載

C#入門

第19回 プリプロセッサとドキュメント

(株)ピーデー
川俣 晶
2002/01/11


複雑な条件の指定

 #ifは、常にシンボル1個しか指定できないわけではない。より高度な指定の例をいくつか紹介しよう。

 1: #define MY_SWITCH1
 2: #undef MY_SWITCH2
 3: using System;
 4:
 5: namespace ConsoleApplication1
 6: {
 7:   class Class1
 8:   {
 9:     static void Main(string[] args)
10:     {
11: #if true
12:       Console.WriteLine("#if true");
13: #endif
14: #if false
15:       Console.WriteLine("#if false");
16: #endif
17: #if MY_SWITCH1 || MY_SWITCH2
18:       Console.WriteLine("MY_SWITCH1 or MY_SWITCH2 is ON");
19: #else
20:       Console.WriteLine("MY_SWITCH1 or MY_SWITCH2 is OFF");
21: #endif
22: #if MY_SWITCH1 && MY_SWITCH2
23:       Console.WriteLine("MY_SWITCH1 and MY_SWITCH2 is ON");
24: #else
25:       Console.WriteLine("MY_SWITCH1 and MY_SWITCH2 is OFF");
26: #endif
27:     }
28:   }
29: }
複雑な条件を使用したサンプル・プログラム6
#ifには「true」、「false」や複数の条件を記述することができる。

 これを実行すると以下のようになる。

サンプル・プログラム6の実行結果
#ifの条件が成立した部分のみが実行されているのが分かる。

 11行目と14行目の条件に記述された「true」と「false」は、それぞれ、「条件が常に成立する」「成立しない」ということを示す定数値である。条件が固定された#ifなど無意味と思われるかもしれないが、ソースを書いている途中で、条件が決まらない段階で#ifによる場合分けを書く場合もある。そういう場合に仮に書き込んでおく用途もある。

 17行目と22行目は、複数のシンボルを参照した条件判断である。「||」と「&&」は、それぞれ、C#の演算子と同じ意味を持つ。「||」は、前後のシンボルのどちらかが定義されているとき、「&&」は前後のシンボルが両方とも定義されているときを意味する。このほかに、一致と不一致を判定する「==」と「!=」も使用できる。また、否定の「!」も使用できる。例えば、「#if MY_SYMBOL」ならシンボルが定義されているときだが、「#if !MY_SYMBOL」とすれば、シンボルが定義されていないとき、となる。

誤った使い方

 ここは、C/C++プログラマ向けの情報である。C/C++にもプリプロセッサがあり、同じような名前を用いるが、必ずしも機能は同じではない。C/C++では正しいが、C#では正しくない例を以下に示す。

 1: #define MY_SYMBOL1 123
 2: #define MY_SYMBOL2(x) Console.WriteLine(x)
 3: using System;
 4:
 5: #define MY_SYMBOL3
 6:
 7: #ifdef MY_SYMBOL4
 8: #endif
 9:
10: namespace ConsoleApplication2
11: {
12:   class Class1
13:   {
14:     static void Main(string[] args)
15:     {
16:       Console.WriteLine("Not Executable");
17:     }
18:   }
19: }
誤った使用法を示すサンプル・プログラム7
このプログラムはコンパイル・エラーとなる。C/C++のプリプロセッサと同じような名前を用いるが、必ずしも機能は同じではない。

 まず1行目。C#では、シンボルは定義できるだけで、値を持たせることはできない。つまり、シンボルに“123”という文字列を関連づけることはできない。2行目のような引数も当然存在しない。5行目は一見正しいように見えるが、C#では、#defineや#undefは、コンパイラ本体が処理するすべてのコードの前に記述される必要がある。このソースでは、3行目のusingステートメントが最初のコードなので、それよりも前に記述しなければならない。7行目は、C/C++プログラマがうっかりミスをしそうな例だが、「#ifdef」はC#には存在せず、「#if」を使う。

複数条件を記述するための#elif

 条件が増えると、#if-#else-#endifだけで記述すると込み入ってしまう場合がある。そういう場合のために「#elif」が用意されている。これは、#elseの機能と#ifの機能が合体したものである。以下はそれを用いた例である。

 1: #define MY_SYMBOL2
 2: using System;
 3:
 4: namespace ConsoleApplication8
 5: {
 6:   class Class1
 7:   {
 8:     static void Main(string[] args)
 9:     {
10: #if MY_SYMBOL1
11:       Console.WriteLine("MY_SYMBOL1");
12: #elif MY_SYMBOL2
13:       Console.WriteLine("MY_SYMBOL2");
14: #elif MY_SYMBOL3
15:       Console.WriteLine("MY_SYMBOL3");
16: #else
17:       Console.WriteLine("no symbols");
18: #endif
19:     }
20:   }
21: }
「#elif」を使用したサンプル・プログラム8
「#elif」を使用することにより、込み入った条件をすっきりと記述することができる。

 これを実行すると以下のようになる。

サンプル・プログラム8の実行結果
4つあるWriteLine呼び出しのうち、“MY_SYMBOL2”の部分のみがコンパイルされる。

 複数条件で#if-#else-#endifを使う場合、#ifを1回記述するごとに、それに対応する#endifを記述しなければならない。つまり、#ifで判定すべき条件が3個あれば、#endifも3個必要になる。しかし、#elifを使えば、上記のように、条件が3個でも#endifは1個しか記述しなくてよい。


 INDEX
  第19回 プリプロセッサとドキュメント
    1.プリプロセッサとは何か
    2.ソースにシンボルの定義を埋め込む
  3.複雑な条件の指定
    4.自作のエラーや警告を発する
    5.XMLドキュメントの埋め込み
    6.利用できるさまざまな要素
 
「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 記事ランキング

本日 月間