実際は、Visual Basic 2005 なんだけど、C# でも同じ、まぁ、実は C 言語でも同じ。
「マジックナンバーを使ってはいけません」というのを小さい頃(プログラミングを始めたばかりの頃ってこと)に教えられた人は、コードの中に即値を入れないようにします。だから、次のように書く…って、書くなぁッ!!!
1 2 3 4 5 6 | const int ZERO = 0; const int TEN = 10; for ( int i = ZERO; i < TEN; i++ ) { // 何かの処理 } |
その…なんというか、顎が外れた。言葉が出ない。
これの応用編(?)として、こんな風なコードもあった…あるなぁッ!!!
1 2 3 4 5 6 7 8 9 | public class CONSTS { public const int ZERO = 0; public const int TEN = 10; } ... for ( int i = CONSTS.ZERO; i < CONSTS.TEN; i++ ) { // 何かの処理 } |
ええっ、思いっきり応用していますね。応用です。鷹揚に構えないと(ぜはぜは)。
で、この手のものをどう書くのですか?と聞かれると、C言語だとこう書きます(実はC#だと悩ましかったり)。
1 2 3 4 5 6 7 | #define MAX 10; ... for ( int i=0; i<MAX; i++ ) { ... } |
「MAX」のところは最大値を示す意味のある言葉を入れるわけで、望ましくないのは「LOOPMAX」とか「COUNTMAX」とかですね。そうなる位であれば「MAX」のほうが潔い。
どうせならば「MAX_TABLES」とか「TABLE_COUNTS」な感じです。
さて、同じようなものをC#で書くと、
1 2 3 4 5 | const int MAX = 10; ... for ( int i=0; i<MAX; i++ ) { ... } |
という感じになりますが、ちょっと違う。この MAX という定義は、C 言語の場合は、関数(メソッド)の外に書くことができるけど、C# や VB の場合は、メソッドの中になってしまう。なので、オブジェクト指向のメリットを活かせば、
1 2 3 4 5 6 7 8 9 | class A { const int MAX = 10; public method() { ... for ( int i=0; i<MAX; i++ ) { ... } } } |
な風に、クラス内の private フィールドにするのが適しているかと。
実は、更に悩ましいことに、この MAX ってのは、共通で使うことが多いので、B クラスでも C クラスでも使うってことになると、
1 2 3 | public class CONSTS { public const MAX = 10; } |
なんていう CONSTS クラスを作っておいて、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class A { public method() { ... for ( int i=0; i<CONSTS.MAX; i++ ) { ... } } } class B { public method() { ... for ( int i=0; i<CONSTS.MAX; i++ ) { ... } } } |
のようにすれば良いのだが、実はこれは隠蔽化を崩している。
新しく D クラスを作った時に、CONSTS.MAX というのが別の意味で使いたい場合に名前が重複してしまう。実務的には、アセンブリを変えるとか、定義名を別にするとかいう方法もあるのですが、実はインターフェースという感覚で
1 2 3 4 5 6 7 8 9 10 | public class CONSTS { public const int MAX = 10; } public class A : CONSTS { public void method() { for ( int i=0; i<MAX; i++ ) { ... } } } |
とするのが妥当かと思うのですが、.NET のクラスでは多重継承ができないので、CONSTS を複数作って継承させるってことができない。
なので、実務的なところでは、
1 2 3 4 5 6 7 8 9 10 11 12 13 | public class TABLE_CONSTS { public const int MAX = 10; } public class PEOPLE_CONSTS { public const int MAX = 100; } public class A { public void method() { for ( int i=0; i<TABLE_CONSTS.MAX; i++ ) { ... } } } |
な風に、CONSTS クラスをあらかじめ分類しておいて、名前空間風に使ってみる、っていうのが普通です…というか、今回はそうしました。
まぁ、CONSTS クラスが多くなるとちょっと…何が何やら分からなくなりますがね。
と・も・か・くッ!!! ONE, TWO THREE のような定義はやめておくなまし。
実は、自動生成をするときに名前を付けるのが面倒くさくて、const int KEY_1 = 1 という書き方をしたのだよね…これがいけなかったな。
const int KEY_JAPAN = “1”
const string NAME_JAPAN = “日本”
のようにするべきだった、と反省。
public class CONSTS {
public const MAX = 10;
}
static抜けてませんか?
これはこれで合っているんすよ。C# では const を付けると自動的に static と同じ扱いになるので、むしろ static を付けるとコンパイルエラーで通らないという現象になります。
あえて static をつけたい場合は static readonly で。