enum
読み:イーナム
外語:enum: enumeration
C/C++/Java、C#、VB.NETなどで、(数値の)列挙型。
概要
enumは、名前を付けた整数定数の集合を用意し、その集合の要素を新たな型として定義する予約語である。
Cの場合は明確な型の定義はなく単なる整数で、その型はintと区別されない。C++やJavaでは、intとは明確に異なる型として処理される。
特徴
利点
#defineで定数をマクロ定義するのに比べ、enumで定義した型を使用すると次のような利点がある。
- コンパイラーによってはswitch文で網羅していないcaseがあると警告してくれる
- enum型を引数にする関数に無関係な値を渡すと警告してくれる
- デバッグ時にenum型は数値ではなくシンボルとして表示してくれる
もちろん、これはツール(コンパイラー、デバッガー)の作りによる。
由来
元々はPascalで搭載されていた機能で、一部のメーカーのCコンパイラーで採用された後、ANSI Cで正式に規格に組み込まれた。
Cでは型があいまいで、値はint相当であるが、signedかunsignedかは実装依存である。負数が含まれればsigned intになるとする実装もある。
Javaでは、public、static、finalな定数を使うことで代わりにしていたが、Java Standard Edition 5.0において、java.lang.Enum型を継承する特殊なクラスとしてenumを定義することが可能になった。
C/C++
C++
Cの場合、単なる定数の列挙に過ぎず、int型との区別は曖昧であった。一方、C++では型が厳密になり、intとは明確に異なる型として処理される。
intへの代入などはCと同様問題なく行なえるが、例えばtry/catch文などにおいてenumの値をthrowしても、これをcatch(int)で捕らえることは出来ない。intではないからである。
以下は失敗する例である。
enum {
ENUM_VER
};
try {
throw ENUM_VAR;
}
catch (const int n) {
...
}
正常に受け取るためには、enumには識別子を付け、それを受け取る形態にせねばならない。
enum sample_enum {
ENUM_VER
};
try {
throw ENUM_VAR;
}
catch (const sample_enum e) {
...
}
sizeof(enum)
C/C++では、enumの要素数を得る直接的な方法はない。sizeof(enum) としても、得られるのは各要素の長さであり、おそらくは sizeof(int) と等価の値でしかない。
あまり望ましくない消極的な方法としては、
enum sample_enum {
a,
b,
c,
number
};
などとして、この number を使用するという方法がある(要素名は任意)。但し、各要素に値を代入しているような場合には、この方法では要素数を求めることができない。
Java
Javaでは、JDK 1.5から対応した。この機能は、C/C++のenumに似た使い方ができる。
public enum Season {
SPRING, SUMMER, FALL, WINTER
}
C/C++とは異なり、実体はクラスで、java.lang.Enum である。このため、Cのような単純なintの列挙とは異なりオブジェクトの列挙となる。
実際に使うときは、Season.SPRING のようにする。メソッドを使うときは、例えば「Season.SPRING.toString()」とすると、"SPRING" という文字列が返される。
なお、switch文で使うときは、判別式には列挙型の変数のみを記述する。つまり、例えば「case Season.SPRING:」ではなく、「case SPRING:」とだけ書けば良い。
再検索