C#には、C++と同じように#if、#endifなんかもありますが、もっとモダンな方法も用意されています。
それがSystem.Diagnostics.ConditionalAttributeクラスです。
|
これを
|
とコンパイルして実行してみてください。
何も表示されずに終了してしまうはずです。
では、今度は
|
とコンパイルして実行してみてください。
今度は"Func1"と表示されたと思います。
/dは/defineの省略形なので"TEST"をdefineするとFunc1メソッドが実行されるわけです。
もちろん、ソースコード中に直接"#define TEST"と書いても同じようにコンパイルされます。
さて、コンパイルされた結果はどうなってるんでしょうか?
ildasmで確認してみましょう(全部書くと長くなるので適当に省略しています)。
|
|
中身は省略してますが、どちらも、Func1メソッドとFunc2メソッドはちゃんとコンパイルされています。 しかし、「何もdefineせずにコンパイルした場合」のMainでは"new Test()"しただけでリターンしています。 「TESTをdefineしてコンパイルした場合」のMainは"new Test()"した後、Func1メソッドを呼び出しています。 どちらのMainにもFunc2メソッドの呼び出しは含まれていません。
こんな風にConditionalAttributeを使うと「文字列がdefineされていないとそのメソッドは無かったことになる」
んですが、メソッド自体はちゃんとコンパイルされて、そのかわりに「そのメソッドを呼び出してるコードが無かったことになる」んです。
もちろん、#ifでも同じことはでます。
けど、#ifだと「呼び出してるほうを#ifで括る」ことになりますが、ConditionalAttributeの場合は「呼ばれるほうにConditionalAttributeを付ける」ことになります。
呼び出してるほうは、あちこちに分散するのが普通ですが、呼ばれるほうは普通1つなので管理しやすいですし、理にもかなってると思います。
そうそう、属性をよく知らない人もいるかもしれませんが、こんな風にクラスやメソッドの直前に[xxxxx]なんて書くのを属性(英語だとAttributeね)といいます。 属性もクラスです(クラスリファレンスに載ってます)。 ただ、[xxxxx]と書くときに"Attribute"は省略していいことになってます(もちろん、書いてもいいです)。 なので、[ConditionalAttribute]と[Conditional]は同じ意味です。 クラス名自体は必ず(絶対じゃないんだけど)Attributeが付いてるので、そのつもりでリファレンスを見てください。 また、[Conditional("TEST")]と書くと、ConditionalAttributeクラスのコンストラクタに"TEST"を渡すという意味になります。