使ってはいけない定数定義の一例

実際は、Visual Basic 2005 なんだけど、C# でも同じ、まぁ、実は C 言語でも同じ。

「マジックナンバーを使ってはいけません」というのを小さい頃(プログラミングを始めたばかりの頃ってこと)に教えられた人は、コードの中に即値を入れないようにします。だから、次のように書く…って、書くなぁッ!!!

const int ZERO = 0;
const int TEN  = 10;

for ( int i = ZERO; i < TEN; i++ ) {
	// 何かの処理
}

その…なんというか、顎が外れた。言葉が出ない。

これの応用編(?)として、こんな風なコードもあった…あるなぁッ!!!


public class CONSTS {
	public const int ZERO = 0;
	public const int TEN  = 10;
}

...
for ( int i = CONSTS.ZERO; i < CONSTS.TEN; i++ ) {
	// 何かの処理
}

ええっ、思いっきり応用していますね。応用です。鷹揚に構えないと(ぜはぜは)。

で、この手のものをどう書くのですか?と聞かれると、C言語だとこう書きます(実はC#だと悩ましかったり)。


#define MAX 10;

...

for ( int i=0; i<MAX; i++ ) {
   ...
}

「MAX」のところは最大値を示す意味のある言葉を入れるわけで、望ましくないのは「LOOPMAX」とか「COUNTMAX」とかですね。そうなる位であれば「MAX」のほうが潔い。
どうせならば「MAX_TABLES」とか「TABLE_COUNTS」な感じです。

さて、同じようなものをC#で書くと、

const int MAX = 10;
...
for ( int i=0; i<MAX; i++ ) {
   ...
}

という感じになりますが、ちょっと違う。この MAX という定義は、C 言語の場合は、関数(メソッド)の外に書くことができるけど、C# や VB の場合は、メソッドの中になってしまう。なので、オブジェクト指向のメリットを活かせば、

class A {
	const int MAX = 10;
	public method() {
		...
		for ( int i=0; i<MAX; i++ ) {
		   ...
		}
	}
}

な風に、クラス内の private フィールドにするのが適しているかと。
実は、更に悩ましいことに、この MAX ってのは、共通で使うことが多いので、B クラスでも C クラスでも使うってことになると、

public class CONSTS {
	public const MAX = 10;
}

なんていう CONSTS クラスを作っておいて、


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 というのが別の意味で使いたい場合に名前が重複してしまう。実務的には、アセンブリを変えるとか、定義名を別にするとかいう方法もあるのですが、実はインターフェースという感覚で

public class CONSTS {
	public const int MAX = 10;
}
public class A : CONSTS {
	public void method() {
		for ( int i=0; i<MAX; i++ ) {
			...
		}
	}
}

とするのが妥当かと思うのですが、.NET のクラスでは多重継承ができないので、CONSTS を複数作って継承させるってことができない。

なので、実務的なところでは、

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 のような定義はやめておくなまし。

カテゴリー: 雑談, C# パーマリンク

使ってはいけない定数定義の一例 への3件のフィードバック

  1. masuda のコメント:

    実は、自動生成をするときに名前を付けるのが面倒くさくて、const int KEY_1 = 1 という書き方をしたのだよね…これがいけなかったな。
    const int KEY_JAPAN = “1”
    const string NAME_JAPAN = “日本”
    のようにするべきだった、と反省。

  2. 匿名 のコメント:

    public class CONSTS {
    public const MAX = 10;
    }

    static抜けてませんか?

    • masuda のコメント:

      これはこれで合っているんすよ。C# では const を付けると自動的に static と同じ扱いになるので、むしろ static を付けるとコンパイルエラーで通らないという現象になります。
      あえて static をつけたい場合は static readonly で。

コメントは停止中です。