列挙型とは何か
プログラムを作成していると、文字列なのだが出現する可能性のある綴りが限定されている、というデータに出会うことがある。例えば、日本の年号は「明治」「大正」「昭和」「平成」と続いているが、これは通常の文字列とは性格が異なっている。文字列なら「太郎」や「花子」を代入してもよいが、それらは年号ではない。かといって、「明治」「大正」「昭和」「平成」を0から3までの整数に割り当ててコーディングしたら、意味不明になってしまう。ある年が「大正」かどうかを判定するために、1かどうか判定する式を書くことになるが、この1が「大正」であることは容易には読みとれない。そこで、数値に名前を割り当ててコーディングしたりするわけだが、C#では、このような目的に適する列挙型(enum)というデータ型が用意されている。今回はこの列挙型について解説する。
まず、最も基本的な列挙型の使用例を以下に示す。
1: using System;
2:
3: namespace ConsoleApplication1
4: {
5: enum Era
6: {
7: Meiji,
8: Taisho,
9: Showa,
10: Heisei
11: }
12: class Class1
13: {
14: static void WriteEra( Era t )
15: {
16: switch( t )
17: {
18: case Era.Meiji:
19: Console.WriteLine("明治");
20: break;
21: case Era.Taisho:
22: Console.WriteLine("大正");
23: break;
24: case Era.Showa:
25: Console.WriteLine("昭和");
26: break;
27: case Era.Heisei:
28: Console.WriteLine("平成");
29: break;
30: }
31: }
32: static void Main(string[] args)
33: {
34: Era t = Era.Taisho;
35: WriteEra( t );
36: }
37: }
38: } |
|
列挙型の基本的な使い方を示したサンプル・プログラム1 |
Eraという名前で、Meiji、Taisho、Showa、Heiseiという4つの名前を含む列挙型を定義している。 |
これを実行すると以下のようになる。
|
サンプル・プログラム1の実行結果 |
列挙型の値“Era.Taisho”に対応した年号を文字列で表示している。
|
まず、列挙型を定義しているのは5〜11行目である。ここでは、Eraという名前で、Meiji、Taisho、Showa、Heiseiという4つの名前を含む列挙型を定義している。Eraはデータ型なので、34行目のようにEra型の変数などを宣言できる。Era型の変数には、上記の4種類の名前しか代入できない。また名前は単独で記述することはできない。つまり、“Era t = Taisho;”と書くことはできず、名前がEra型であることを明示するために、名前の手前に“Era.”を付加して、“Era t = Era.Taisho;”と記述しなければならない。
宣言された列挙型は、文字列というよりも数値のように振る舞うと考えておけば間違いない。実際、後で述べるように中身は数値として処理される。しかしほとんどの場合、列挙型は数値とは異なる意味を与えられているので、16〜30行目のswitch文に見られるように、各要素を独立して判断し、処理を決めるのが基本になる。上級者になれば、列挙型を数値扱いするトリックを使うことで、処理効率をアップしたり、プログラムを短くしたりすることもできるが、トラブルの元なので、こうした使い方は初心者にはお勧めしない。
列挙型をConsole.WriteLineする
いちばん手軽に値を出力できるConsole.WriteLineメソッドは、この連載はもとより、お世話になっているC#プログラマも多いと思う。このメソッドに直接列挙型の値を渡したら何が起こるだろうか。実際にやってみたものが、以下のサンプル・ソースである。
1: using System;
2:
3: namespace ConsoleApplication2
4: {
5: enum Era
6: {
7: Meiji,
8: Taisho,
9: Showa,
10: Heisei
11: }
12: class Class1
13: {
14: static void Main(string[] args)
15: {
16: Era t = Era.Taisho;
17: Console.WriteLine( t );
18: }
19: }
20: } |
|
列挙型の値を表示するサンプル・プログラム2 |
列挙型の値を直接Console.WriteLineメソッドに渡してみる。 |
これを実行すると以下のようになる。
|
サンプル・プログラム2の実行結果 |
列挙型の値の名前そのものが出力された。
|
この実行結果を見て分かるとおり、列挙型をConsole.WriteLineメソッドに直接渡すと、その名前そのものが出力される。C++プログラマは、この点で挙動が異なることに注意していただきたい。C++では、このような場合、名前ではなく数値が出力されてしまうのである。C++の列挙型は数値の別名にすぎないが、C#の列挙型はもう少し多くの管理情報を実行時に持っていて、機能的にイコールではない。
列挙型で漢字を使う
C#はキーワードに漢字を使用できる。では年号を漢字で書いたら何が起こるだろうか? 以下がその例である。
1: using System;
2:
3: namespace ConsoleApplication2
4: {
5: enum Era
6: {
7: 明治,
8: 大正,
9: 昭和,
10: 平成
11: }
12: class Class1
13: {
14: static void Main(string[] args)
15: {
16: Era t = Era.大正;
17: Console.WriteLine( t );
18: }
19: }
20: } |
|
列挙型の値に漢字を用いたサンプル・プログラム3 |
C#はキーワードに漢字を使用できる。列挙型の値に漢字を使用し、Console.WriteLineメソッドに渡してみる。 |
これを実行すると以下のようになる。
|
サンプル・プログラム3の実行結果 |
漢字で書かれたキーワードがそのままコンソールに出力される。
|
見てのとおり、漢字で記述したキーワードがそのままコンソールに出力されている。この程度のシンプルなデータなら、最初のサンプル・ソースのように、いちいちswitch文で処理を切り分けるのではなく、最初から目的の名前を列挙型定義で書いてしまっても問題ないだろう。ただし、名前に使用できる文字には制限がある(例えば空白文字や区切りのカンマなどは書けない)ので、この手法はいつでも利用可能というわけではない。
最後の要素に付くカンマ
小さいトピックだが、以下のソースコードの10行目を見ていただきたい。
1: using System;
2:
3: namespace ConsoleApplication2
4: {
5: enum Era
6: {
7: Meiji,
8: Taisho,
9: Showa,
10: Heisei,
11: }
12: class Class1
13: {
14: static void Main(string[] args)
15: {
16: Era t = Era.Taisho;
17: Console.WriteLine( t );
18: }
19: }
20: } |
|
最後の要素にカンマを付けたサンプル・プログラム4 |
10行目の“Heisei,”に注目。 |
これを実行すると以下のようになる。
|
サンプル・プログラム4の実行結果 |
列挙型の最後の項目にカンマが付いていてもエラーにならない。
|
リストの10行目を見て分かるとおり、C#では列挙型の最後の項目にカンマが付いていてもエラーにならない。普通に考えればカンマは項目の区切りに入れるもので、後ろに項目もないのにカンマを書いて終わるのは不自然に見えるかも知れない。だが、項目とカンマのペアを書いていると思えば、最後の項目だけカンマを付けないというのは、不自然に見える。特に、項目とカンマのペアを繰り返し出力するプログラムでソースを自動生成する場合など、最後の場合だけカンマを付けないというルールを入れると処理が複雑になってしまう。そのようなことから、最後の項目の後ろのカンマは、あってもなくても許すような仕様になっている。
Insider.NET 記事ランキング
本日
月間