C# では、列挙型(enumeration type)と呼ばれるものを利用することで、曜日などの特定の値しかとらないデータを表現することが出来ます。
例えば、曜日は月・火・水・木・金・土・日の7つの値しか取りませんし、 英語の月は January, February, March, April, May, June, July, August, September, October, November, December の12個の値しか取りません。 その他にも、 飛行機の乗車クラス(エコノミー・ビジネス・ファースト)、 日本の年号(明治・大正・昭和・平成)、 性別(男・女)など、特定の値しか取らないものはたくさんあります。 C# で、このような特定の値しか取らない型を表現するためには列挙型というものを使います。
列挙型は以下のようにして定義します。
enum 列挙型名 { メンバ1, メンバ2, …, メンバn }
列挙型を利用する側では以下のようにします。
列挙型名.メンバ名
また、列挙型の値を Console.Write などに渡して表示すると、
メンバ名がそのまま表示されます。
例えば、和暦の年号を列挙型として定義すると以下のようになります。
using System; enum 年号 { 明治, 大正, 昭和, 平成 } class EnumSample { /// <summary> /// 和暦を西暦に変換する /// </summary> public static void Main() { 年号[] era = new 年号[5]{年号.昭和, 年号.大正, 年号.明治, 年号.平成, 年号.昭和}; int[] j_year = new int[5]{33, 12, 20, 10, 54}; int[] year = new int[5]; Console.Write("和暦 西暦\n"); for(int i=0; i<5; ++i) { switch(era[i]) { case 年号.明治: year[i] = j_year[i] + 1863; break; case 年号.大正: year[i] = j_year[i] + 1911; break; case 年号.昭和: year[i] = j_year[i] + 1925; break; case 年号.平成: year[i] = j_year[i] + 1988; break; } Console.Write("{0}{1:d2}年 {2:d4}年\n", era[i], j_year[i], year[i]); } } }
和暦 西暦 昭和33年 1958年 大正12年 1923年 明治20年 1883年 平成10年 1998年 昭和54年 1979年
列挙型はプログラムの内部では整数として扱われていて、
整数型に変換することでその値を取り出すことが出来ます。
特に値や型を指定しなければ、列挙型は int として扱われ、
各メンバは宣言した順番に 0, 1, 2, …, n となります。
例えば以下のような列挙型を定義すると、
Mon, Tue, Wed, Thu, Fri, Sat, Sun
の値はそれぞれ 0, 1, 2, 3, 4, 5, 6 になります。
enum DayOfWeek
{
Mon, Tue, Wed, Thu, Fri, Sat, Sun
}
列挙型の型や値は以下のようにすることで明示的に指定することも出来ます。
enum 列挙型名 : 内部的な型 { メンバ1 = メンバ1の値, メンバ2 = メンバ2の値, …, メンバn = メンバnの値 }
また、1つ目のメンバだけに値を指定すると、残りのメンバの値は1つ目のメンバの値から1ずつ増加した値になります。
例えば、byte 型で、値が1から始まる列挙型を定義したければ以下のようにします。
enum Month : byte { January = 1, February, March, April, May, June, July, August, September, October, November, December } class EnumSample { public static void Main() { for(int i=1; i<12; ++i) Console.Write("{0}月 {1}\n", i, (Month)i); } }
1月 January 2月 February 3月 March 4月 April 5月 May 6月 June 7月 July 8月 August 9月 September 10月 October 11月 November
ちなみに、この例から分かるように、 列挙型を文字列化(ToString)すると、列挙型のメンバ名が表示されます。
ときには、以下のような定数を定義したい場合もあります。
こういう場合、列挙型を以下のように使って実現したりします。
enum Xyz { X = 1, // 001 Y = 2, // 010 Z = 4, // 100 } class Program { static void Main(string[] args) { Xyz xy = Xyz.X | Xyz.Y; // 011 ... }
列挙型の値を2の累乗にして、OR 演算をとります。
ただし、このままだと、Console.Write を使って表示するときに少し困ります。 以下の例の場合、X | Y は 3 になるわけですが、値が3のメンバは Xyz 列挙型には定義されていないので、 表示結果は数値の3がそのまま表示されます。
enum Xyz { X = 1, // 001 Y = 2, // 010 Z = 4, // 100 } class Program { static void Main(string[] args) { Console.Write("{0}\n", Xyz.X); Console.Write("{0}\n", Xyz.Y); Console.Write("{0}\n", Xyz.Z); Xyz xy = Xyz.X | Xyz.Y; Console.Write("{0}\n", xy); } }
X Y Z 3
これに対して、列挙型に Flags 属性を付けると、以下のような表示結果が得られるようになります。 (属性に関しては 「属性」 を参照。)
[Flags] enum Xyz { X = 1, // 001 Y = 2, // 010 Z = 4, // 100 } class Program { static void Main(string[] args) { Xyz xy = Xyz.X | Xyz.Y; Console.Write("{0}\n", xy); Xyz yz = Xyz.Y | Xyz.Z; Console.Write("{0}\n", yz); Xyz zx = Xyz.Z | Xyz.X; Console.Write("{0}\n", zx); Xyz xyz = Xyz.X | Xyz.Y | Xyz.Z; Console.Write("{0}\n", xyz); } }
X, Y Y, Z X, Z X, Y, Z