2010-09-27T06:09:00の更新内容

programming/netfx2/overview/enumtype/index.wiki.txt

current previous
3,113 3,73
 
今更列挙型とは何かという初歩的なことを詳しくは説明しませんが、列挙型を用いるとはっきりとした意味を持った一連の数値定数を扱うことができます。 列挙型がなくても定数を使うことも当然できますが、定数では互いに関連する一連の数値定数でもバラバラに扱われ、単なる数値(または文字列など)の置き換え程度の機能しか持ち得ません。
今更列挙型とは何かという初歩的なことを詳しくは説明しませんが、列挙型を用いるとはっきりとした意味を持った一連の数値定数を扱うことができます。 列挙型がなくても定数を使うことも当然できますが、定数では互いに関連する一連の数値定数でもバラバラに扱われ、単なる数値(または文字列など)の置き換え程度の機能しか持ち得ません。
 
#googleadunit
#googleadunit
 

        

        
~
*列挙型の基本
*もっとも基本的な列挙型の使い方
 
列挙型の様々な機能を説明するのに先立って、もっとも基本的な列挙型の使い方の例を挙げてみます。
列挙型の様々な機能を説明するのに先立って、もっとも基本的な列挙型の使い方の例を挙げてみます。
+
#tabpage(C#)
 
#code(cs){{
#code(cs){{
 
using System;
using System;
 

        

        
~
// 方角を表す列挙型
namespace AboutEnumType
+
enum Direction
 
{
{
~
  North,
    // 方角を表す列挙型
~
  West,
    enum Direction
~
  South,
    {
~
  East,
        North,
~
}
        West,
-
        South,
-
        East,
-
    }
 

        

        
~
class EnumSample
    // アプリケーションのエントリーポイントを提供するクラス
~
{
    class AboutEnumType
~
  static void Main()
    {
~
  {
        [STAThread]
~
    Direction d = Direction.North;
        static void Main(string[] args)
-
        {
-
            Direction d = Direction.North;
 

        

        
~
    if (d == Direction.North) Console.WriteLine( "d は北向きです" );
            if ( d == Direction.North ) Console.WriteLine( "d は北向きです" );
~
  }
        }
-
    }
 
}
}
 
}}
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
' 方角を表す列挙型
+
Enum Direction
+
  North
+
  West
+
  South
+
  East
+
End Enum
+

          
+
Class EnumSample
+
  Shared Sub Main()
+
    Dim d As Direction = Direction.North
+

          
+
    If d = Direction.North Then Console.WriteLine("d は北向きです")
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
~
実行結果については省略しますが「d は北向きです」と表示されるはずです。 この例のように、東西南北という一連の方角を表す定数は、それぞれバラバラに存在するよりも一つのグループとして存在しているべきです。
実行結果については省略しますが「d は北向きです」と表示されるはずです。 この例のように、東西南北という一連の方角を表す定数は、それぞれバラバラに存在するよりも一つのグループとして存在しているべきです。 もちろん、何らかの理由で単なる定数としてあつかった方がよい場合もあります。
 

        

        
~
もちろん、何らかの理由で単なる定数としてあつかった方がよい場合もありますが、一方で、列挙型の場合は値としても名前(つまり値の意味)としても表記でき、それらを結びつけておくことが出来ます。 定数では、定数として与えられているその値しか表記できません。
ただ、列挙型の値は文字列や数値として、列挙型定数の値の持つ意味を表すこともできます。 定数では、定数として与えられているその値しか持ち得ません。 その例を次に挙げます。
 

        

        
~
#tabpage(C#)
#code(cs,列挙型定数の値の持つ意味){{
+
#code(cs,列挙型定数の値と値の意味){{
 
using System;
using System;
 

        

        
~
// 方角を表す列挙型
namespace AboutEnumType
+
enum Direction
 
{
{
~
  North,
    // 方角を表す列挙型
~
  West,
    enum Direction
~
  South,
    {
~
  East,
        North,
~
}
        West,
-
        South,
-
        East,
-
    }
 

        

        
~
class EnumSample
    // アプリケーションのエントリーポイントを提供するクラス
~
{
    class AboutEnumType
~
  static void Main()
    {
~
  {
        [STAThread]
~
    Direction d = Direction.North;
        static void Main(string[] args)
~

          
        {
~
    Console.WriteLine("d の方角は {0} です。", d);
            Direction d = Direction.North;
~
    Console.WriteLine("d の持つ値は {0} です。", (int)d);

          
~

          
            Console.WriteLine( "d の方角は {0} です。", d );
~
    Console.WriteLine("Direction.North の持つ値は {0} です。", (int)Direction.North);
            Console.WriteLine( "d の持つ値は {0} です。", (int)d );
~
    Console.WriteLine("Direction.West の持つ値は {0} です。", (int)Direction.West);

          
~
    Console.WriteLine("Direction.South の持つ値は {0} です。", (int)Direction.South);
            Console.WriteLine( "Direction.North の持つ値は {0} です。", (int)Direction.North );
~
    Console.WriteLine("Direction.East の持つ値は {0} です。", (int)Direction.East);
            Console.WriteLine( "Direction.West の持つ値は {0} です。", (int)Direction.West );
~
  }
            Console.WriteLine( "Direction.South の持つ値は {0} です。", (int)Direction.South );
-
            Console.WriteLine( "Direction.East の持つ値は {0} です。", (int)Direction.East );
-
        }
-
    }
 
}
}
 
}}
}}
+
#tabpage(VB)
+
#code(vb,列挙型定数の値の持つ意味){{
+
Imports System
+

          
+
' 方角を表す列挙型
+
Enum Direction
+
  North
+
  West
+
  South
+
  East
+
End Enum
+

          
+
Class EnumSample
+
  Shared Sub Main()
+
    Dim d As Direction = Direction.North
+

          
+
    Console.WriteLine("d の方角は {0} です。", d)
+
    Console.WriteLine("d の持つ値は {0} です。", CInt(d))
+

          
+
    Console.WriteLine("Direction.North の持つ値は {0} です。", CInt(Direction.North))
+
    Console.WriteLine("Direction.West の持つ値は {0} です。", CInt(Direction.West))
+
    Console.WriteLine("Direction.South の持つ値は {0} です。", CInt(Direction.South))
+
    Console.WriteLine("Direction.East の持つ値は {0} です。", CInt(Direction.East))
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
 
#prompt(実行結果){{
#prompt(実行結果){{
 
dの方角は North です。
dの方角は North です。
121,64 81,42
 
Press any key to continue
Press any key to continue
 
}}
}}
 

        

        
~
このように、列挙型の値の名前を文字列として表記することも可能ですし、値が内部的に保持している数値として表記することも可能です。 このように、列挙型の値が数値を持つだけでなく、意味も同時に持つことができる点で単なる定数より優れているといえます。
このように、列挙型の値を文字列として表記することも可能ですし、値が内部的に保持している数値として表記することも可能です。 このように、列挙型の値が数値を持つだけでなく、意味も同時に持つことができる点で定数より優れているといえます。
 

        

        
~
*列挙型の値と型
*列挙型定数の値と型
+
**列挙型定数の値
 
列挙型の定数一つ一つを宣言する際に、値を指定することができます。 なにも指定しない場合は、上から順に0, 1, 2...となっていきます。 その定数に特別な数値を与える場合、数値が意味を持つ場合には数値を指定することができます。
列挙型の定数一つ一つを宣言する際に、値を指定することができます。 なにも指定しない場合は、上から順に0, 1, 2...となっていきます。 その定数に特別な数値を与える場合、数値が意味を持つ場合には数値を指定することができます。
 

        

        
+
#tabpage(C#)
 
#code(cs,列挙型定数に値を与える){{
#code(cs,列挙型定数に値を与える){{
 
using System;
using System;
 

        

        
~
// 上下方向を表す列挙型
namespace AboutEnumType
+
enum UpAndDown
 
{
{
~
  Up   =  1,
    // 上下方向を表す列挙型
~
  Down = -1,
    enum UpAndDown
~
  None =  0,
    {
~
}
        Up   =  1,
-
        Down = -1,
-
        None =  0,
-
    }
 

        

        
~
class EnumSample
    // アプリケーションのエントリーポイントを提供するクラス
~
{
    class AboutEnumType
~
  static void Main()
    {
~
  {
        [STAThread]
~
    int locationY = 5;
        static void Main(string[] args)
~
    UpAndDown upDown = UpAndDown.Down;
        {
-
            int locationY = 5;
-
            UpAndDown upDown = UpAndDown.Down;
 

        

        
~
    Console.WriteLine("upDown の方向は {0} です。", upDown);
            Console.WriteLine( "upDown の方向は {0} です。", upDown );
 

        

        
~
    locationY += (int)upDown;
            locationY += (int)upDown;
 

        

        
~
    Console.WriteLine("locationY の位置は {0} です。", locationY);
            Console.WriteLine( "locationY の位置は {0} です。", locationY );
~
  }
        }
-
    }
 
}
}
 
}}
}}
+
#tabpage(VB)
+
#code(vb,列挙型定数に値を与える){{
+
Imports System
+

          
+
' 上下方向を表す列挙型
+
Enum UpAndDown
+
  Up = 1
+
  Down = -1
+
  None =  0
+
End Enum
+

          
+
Class EnumSample
+
  Shared Sub Main()
+
    Dim locationY As Integer = 5
+
    Dim upDown As UpAndDown = UpAndDown.Down
+

          
+
    Console.WriteLine("upDown の方向は {0} です。", upDown)
+

          
+
    locationY += CInt(upDown)
+

          
+
    Console.WriteLine("locationY の位置は {0} です。", locationY)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
 
#prompt(実行結果){{
#prompt(実行結果){{
 
upDown の方角は Down です。
upDown の方角は Down です。
186,59 124,38
 
Press any key to continue
Press any key to continue
 
}}
}}
 

        

        
~
この例では上下方向を表す列挙型UpAndDownを宣言し、その各定数に値を与えています。 そして、upDownが上下(または方向なし)のうちどこを向いているかによってY座標の位置をずらしています。 このように、列挙型定数の値を直接利用することができます。
この例では上下方向を表す列挙型UpAndDownを宣言し、その各定数に値を与えています。 そして、upDownが上下(または方向なし)のうちどこを向いているかによってY座標の位置をずらしています。 このように、列挙型定数の値を直接利用することができます。 また、複数の列挙型定数に同じ値を設定することができますが、その場合は次の例で示すような現象が発生します。
+
値を与える場合、複数の列挙型定数に同じ値を設定することができますが、その場合は次の例で示すような現象が発生します。
 

        

        
+
#tabpage(C#)
 
#code(cs,列挙型定数に同じ値を指定する){{
#code(cs,列挙型定数に同じ値を指定する){{
 
using System;
using System;
 

        

        
~
// 同じ値を持つ列挙型
namespace AboutEnumType
+
enum SameValueEnum
 
{
{
~
  ValueA = 0,
    // 列挙型
~
  ValueB = 1,
    enum SameValueEnum
~
  ValueC = ValueA,
    {
~
}
        ValueA = 0,
-
        ValueB = 1,
-
        ValueC = ValueA,
-
    }
 

        

        
~
class EnumSample
    // アプリケーションのエントリーポイントを提供するクラス
~
{
    class AboutEnumType
~
  static void Main()
    {
~
  {
        [STAThread]
~
    SameValueEnum e = SameValueEnum.ValueB;
        static void Main(string[] args)
-
        {
-
            SameValueEnum e = SameValueEnum.ValueB;
 

        

        
~
    Console.WriteLine("e: {0}", e);
            Console.WriteLine( "e: {0}", e );
 

        

        
~
    e = SameValueEnum.ValueC;
            e = SameValueEnum.ValueC;
 

        

        
~
    Console.WriteLine("e: {0}", e);
            Console.WriteLine( "e: {0}", e );
~
  }
        }
-
    }
 
}
}
 
}}
}}
+
#tabpage(VB)
+
#code(vb,列挙型定数に同じ値を指定する){{
+
Imports System
+

          
+
' 同じ値を持つ列挙型
+
Enum SameValueEnum
+
  ValueA = 0
+
  ValueB = 1
+
  ValueC = ValueA
+
End Enum
+

          
+
Class EnumSample
+
  Shared Sub Main()
+
    Dim e As SameValueEnum = SameValueEnum.ValueB
+

          
+
    Console.WriteLine("e: {0}", e)
+

          
+
    e = SameValueEnum.ValueC
+

          
+
    Console.WriteLine("e: {0}", e)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
 
#prompt(実行結果){{
#prompt(実行結果){{
 
e: ValueB
e: ValueB
248,306 165,191
 

        

        
 
この例ではSameValueEnumのValueCにValueAと同じ値を指定しています。 実行結果を見てわかるとおり、一度目の表示では正しく ValueBが表示されていますが、二度目の表示ではeにValueCを割り当てたはずなのにValueAと出力されてしまっています。 これは列挙型の定数は内部では結局数値として扱われてしまうのでこのようになるのです。 ValueAとValueCに相当する定数が互いに別名であるような場合には問題ありませんが、この例のようにValueCと出力されることを期待する場合には注意が必要です。
この例ではSameValueEnumのValueCにValueAと同じ値を指定しています。 実行結果を見てわかるとおり、一度目の表示では正しく ValueBが表示されていますが、二度目の表示ではeにValueCを割り当てたはずなのにValueAと出力されてしまっています。 これは列挙型の定数は内部では結局数値として扱われてしまうのでこのようになるのです。 ValueAとValueCに相当する定数が互いに別名であるような場合には問題ありませんが、この例のようにValueCと出力されることを期待する場合には注意が必要です。
 

        

        
~
**列挙型定数の型
さらに、このように列挙型定数の値を直接利用するようになると、列挙型定数の値の型が気になってきます。 そのような場合、列挙型の値の型を明示的に指定することができます。 指定できる型は、列挙型の性質からchar型以外の整数型に限られます。 また、なにも指定しなかった場合は既定でintになります。 次の例は列挙型定数の型をshortにした例です。
+
先の例のように列挙型定数の値を直接利用するようになると、列挙型定数の値の型が気になってきます。 そのような場合、列挙型の値の型を明示的に指定することができます。 指定できる型は、列挙型の性質からchar型以外の整数型に限られます。 また、なにも指定しなかった場合は既定でint(Integer)になります。 次の例は列挙型定数の型をshortにした例です。
 

        

        
~
#tabpage(C#)
#code(cs,列挙型定数の値の型){{
+
#code(cs,列挙型の型を指定する){{
 
using System;
using System;
 

        

        
~
// 上下方向を表す列挙型
namespace AboutEnumType
+
enum UpAndDown : short
 
{
{
~
  Up   =  1,
    // 上下方向を表す列挙型
~
  Down = -1,
    enum UpAndDown : short
~
  None =  0,
    {
~
}
        Up   =  1,
-
        Down = -1,
-
        None =  0,
-
    }
 

        

        
~
class EnumSample
    // アプリケーションのエントリーポイントを提供するクラス
~
{
    class AboutEnumType
~
  static void Main()
    {
~
  {
        [STAThread]
~
    short locationY = 5;
        static void Main(string[] args)
~
    UpAndDown upDown = UpAndDown.Down;
        {
-
            short locationY = 5;
-
            UpAndDown upDown = UpAndDown.Down;
 

        

        
~
    Console.WriteLine("upDown の方向は {0} です。", upDown);
            locationY += (short)upDown;
 

        

        
~
    locationY += (short)upDown;
            Console.WriteLine( "locationY の位置は {0} です。", locationY );
~

          
        }
~
    Console.WriteLine("locationY の位置は {0} です。", locationY);
    }
+
  }
 
}
}
 
}}
}}
+
#tabpage(VB)
+
#code(vb,列挙型の型を指定する){{
+
Imports System
+

          
+
' 上下方向を表す列挙型
+
Enum UpAndDown As Short
+
  Up = 1
+
  Down = -1
+
  None =  0
+
End Enum
+

          
+
Class EnumSample
+
  Shared Sub Main()
+
    Dim locationY As Short = 5
+
    Dim upDown As UpAndDown = UpAndDown.Down
+

          
+
    Console.WriteLine("upDown の方向は {0} です。", upDown)
+

          
+
    locationY += CShort(upDown)
+

          
+
    Console.WriteLine("locationY の位置は {0} です。", locationY)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
 
*列挙型に対する様々な操作
*列挙型に対する様々な操作
~
列挙型は単純な定数に比べ様々な機能を持っています。 また、列挙型に対する操作もいろいろあります。 列挙型の暗黙の基底クラスであるEnum型には様々な静的メソッドが存在します。
列挙型は定数に比べ様々な機能を持っています。 また、列挙型に対する操作もいろいろあります。 列挙型の暗黙の基底クラスであるEnum型には様々な静的メソッドが存在します。 次の例はその内のGetName()メソッドを使用したものです。 このメソッドは列挙型と数値から、その列挙型にあってその数値をもつ定数の名前を取得するものです。
+

          
+
**Enum.GetName()メソッド
+
&msdn(netfx,method,System.Enum.GetName){GetName()メソッド};を使用すると、指定された値から該当する数値をもつ列挙型の定数の名前を取得することが出来ます。
 

        

        
+
#tabpage(C#)
 
#code(cs,列挙型定数の名前の取得){{
#code(cs,列挙型定数の名前の取得){{
 
using System;
using System;
 

        

        
~
// 方角を表す列挙型
namespace AboutEnumType
+
enum Direction : int
+
{
+
  North = -1,
+
  West  = -2,
+
  South =  1,
+
  East  =  2,
+
  None  =  0,
+
}
+

          
+
class EnumSample
 
{
{
~
  static void Main()
    // 方角を表す列挙型
~
  {
    enum Direction : int
~
    string name;
    {
-
        North = -1,
-
        West  = -2,
-
        South =  1,
-
        East  =  2,
-
        None  =  0,
-
    }
 

        

        
~
    // --3 から 3 までの値が示すDirectionの名前を表示する
    // アプリケーションのエントリーポイントを提供するクラス
~
    for (int i = -3; i <= 3; i++)
    class AboutEnumType
 
    {
    {
~
      // iの値と同じ値を持つ列挙型定数の名前を取得
        [STAThread]
~
      name = Enum.GetName(typeof(Direction), i);
        static void Main(string[] args)
~

          
        {
~
      Console.WriteLine("{0} means {1}", i, name);
            string name;
-

          
-
            // -2 から 3 までの値が示すDirectionの名前を表示する
-
            for ( int i = -2; i <= 3; i++ )
-
            {
-
                // iの値と同じ値を持つ列挙型定数の名前を取得
-
                name = Enum.GetName( typeof( Direction ), i );
-

          
-
                Console.WriteLine( "{0} means {1}", i, name );
-
            }
-
        }
 
    }
    }
+
  }
 
}
}
 
}}
}}
+
#tabpage(VB)
+
#code(vb,列挙型定数の名前の取得){{
+
Imports System
+

          
+
' 方角を表す列挙型
+
Enum Direction As Integer
+
  North = -1
+
  West  = -2
+
  South = 1
+
  East  = 2
+
  None  = 0
+
End Enum
+

          
+
Class EnumSample
+
  Shared Sub Main()
+
    Dim name As String
+

          
+
    ' --3 から 3 までの値が示すDirectionの名前を表示する
+
    For i As Integer = -3 To 3
+
      ' iの値と同じ値を持つ列挙型定数の名前を取得
+
      name = System.Enum.GetName(GetType(Direction), i)
+

          
+
      Console.WriteLine("{0} means {1}", i, name)
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
 
#prompt(実行結果){{
#prompt(実行結果){{
+
-3 means 
 
-2 means West
-2 means West
 
-1 means North
-1 means North
 
0 means None
0 means None
 
1 means South
1 means South
 
2 means East
2 means East
~
3 means 
3 means
 
Press any key to continue
Press any key to continue
 
}}
}}
 

        

        
~
このように、指定された数値に対応する定数の名前を取得することができます。 また、対応する定数がない場合はnullが返されます。
このように、指定された数値に対応する定数の名前を取得することができます。 また、対応する定数がない場合はnullが返されます。 単一の値から名前を取得するのではなく、列挙型内に含まれるすべての定数の名前を取得するにはGetNames()メソッドを、すべての定数の値を取得するには GetValues()メソッドを使用します。 この例を次に示します。
+

          
+
**Enum.GetNames()メソッド、Enum.GetValues()メソッド
+
単一の値から名前を取得するのではなく、列挙型内に含まれるすべての定数の名前を取得するには&msdn(netfx,method,System.Enum.GetNames){GetNames()メソッド};メソッドを、すべての定数の値を取得するには &msdn(netfx,method,System.Enum.GetValues){GetValues()メソッド};を使用します。 この例を次に示します。
 

        

        
+
#tabpage(C#)
 
#code(cs,列挙型に含まれるすべての名前、値を取得する){{
#code(cs,列挙型に含まれるすべての名前、値を取得する){{
 
using System;
using System;
 

        

        
~
// 方角を表す列挙型
namespace AboutEnumType
+
enum Direction : int
+
{
+
  North = -1,
+
  West  = -2,
+
  South =  1,
+
  East  =  2,
+
  None  =  0,
+
}
+

          
+
class EnumSample
 
{
{
~
  static void Main()
    // 方角を表す列挙型
~
  {
    enum Direction : int
+
    // Directionの持つ名前
+
    string[] names = Enum.GetNames(typeof(Direction));
+

          
+
    Console.WriteLine("'Direction' has following names");
+

          
+
    foreach (string name in names)
 
    {
    {
~
      Console.WriteLine("  {0}", name);
        North = -1,
-
        West  = -2,
-
        South =  1,
-
        East  =  2,
-
        None  =  0,
 
    }
    }
 

        

        
~
    // Directionの持つ値
    // アプリケーションのエントリーポイントを提供するクラス
~
    Array values = Enum.GetValues(typeof(Direction));
    class AboutEnumType
+

          
+
    Console.WriteLine("'Direction' has following values");
+

          
+
    foreach (int val in values)
 
    {
    {
~
      Console.WriteLine("  {0}", val);
        [STAThread]
-
        static void Main(string[] args)
-
        {
-
            // Directionの持つ名前
-
            string[] names = Enum.GetNames( typeof( Direction ) );
-

          
-
            Console.WriteLine( "'Direction' has following names" );
-

          
-
            foreach ( string name in names )
-
            {
-
                Console.WriteLine( "\t{0}", name );
-
            }
-

          
-
            // Directionの持つ値
-
            Array values = Enum.GetValues( typeof( Direction ) );
-

          
-
            Console.WriteLine( "'Direction' has following values" );
-

          
-
            foreach ( int val in values )
-
            {
-
                Console.WriteLine( "\t{0}", val );
-
            }
-
        }
 
    }
    }
+
  }
 
}
}
 
}}
}}
+
#tabpage(VB)
+
#code(vb,列挙型に含まれるすべての名前、値を取得する){{
+
Imports System
+

          
+
' 方角を表す列挙型
+
Enum Direction As Integer
+
  North = -1
+
  West  = -2
+
  South = 1
+
  East  = 2
+
  None  = 0
+
End Enum
+

          
+
Class EnumSample
+
  Shared Sub Main()
+
    ' Directionの持つ名前
+
    Dim names As String() = System.Enum.GetNames(GetType(Direction))
+

          
+
    Console.WriteLine("'Direction' has following names")
+

          
+
    For Each name As String In names
+
      Console.WriteLine("  {0}", name)
+
    Next
+

          
+
    ' Directionの持つ値
+
    Dim values As Array = System.Enum.GetValues(GetType(Direction))
+

          
+
    Console.WriteLine("'Direction' has following values")
+

          
+
    For Each val As Integer In values
+
      Console.WriteLine("  {0}", val)
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
 
#prompt(実行結果){{
#prompt(実行結果){{
 
'Direction' has following names
'Direction' has following names
~
  None
        None
~
  South
        South
~
  East
        East
~
  West
        West
~
  North
        None
 
'Direction' has following values
'Direction' has following values
~
  0
        0
~
  1
        1
~
  2
        2
~
  -2
        -2
~
  -1
        -1
 
Press any key to continue
Press any key to continue
 
}}
}}
 

        

        
~
Enum.GetValues()メソッドが実際に返す配列の型は、列挙型の値の型と同じものになります。 int(Integer)型の列挙型の場合は、int(Integer)型の配列が返されます。
さらに、任意の値が列挙型定数として宣言されているか否かを知ることもできます。
 

        

        
+
**Enum.IsDefined()メソッド
+
任意の値が列挙型定数として宣言されているか否かを知るには、&msdn(netfx,method,System.Enum.IsDefined){IsDefined()メソッド};を使用します。
+

          
+
#tabpage(C#)
 
#code(cs,列挙型定数として宣言されているかを知る){{
#code(cs,列挙型定数として宣言されているかを知る){{
 
using System;
using System;
 

        

        
~
// 方角を表す列挙型
namespace AboutEnumType
+
enum Direction : int
 
{
{
~
  North = -1,
    // 方角を表す列挙型
~
  West  = -2,
    enum Direction : int
~
  South =  1,
    {
~
  East  =  2,
        North = -1,
~
  None  =  0,
        West  = -2,
~
}
        South =  1,
~

          
        East  =  2,
~
class EnumSample
        None  =  0,
~
{
    }
~
  static void Main()

          
~
  {
    // アプリケーションのエントリーポイントを提供するクラス
~
    Type t = typeof(Direction);
    class AboutEnumType
~

          
    {
~
    for (int i = -3; i <= 3; i++)
        [STAThread]
~
    {
        static void Main(string[] args)
~
      // その値は定数として宣言されているか
        {
~
      if (Enum.IsDefined(t, i))
            Type t = typeof( Direction );
~
      {

          
~
          Console.WriteLine("{0} is defined in {1} as {2}.", i, t.Name, Enum.GetName(t, i));
            for ( int i = -3; i <= 3; i++ )
~
      }
            {
~
      else
                // その値は定数として宣言されているか
~
      {
                if ( Enum.IsDefined( t, i ) )
~
          Console.WriteLine("{0} is not defined in {1}.", i, t.Name);
                {
~
      }
                    Console.WriteLine( "{0} is defined in {1} as {2}.", i, t.Name, Enum.GetName( t, i ) );
~
    }
                }
~
  }
                else
~
}
                {
~
}}
                    Console.WriteLine( "{0} is not defined in {1}.", i, t.Name );
~
#tabpage(VB)
                }
~
#code(vb,列挙型定数として宣言されているかを知る){{
            }
~
Imports System
        }
~

          
    }
~
' 方角を表す列挙型
}
+
Enum Direction As Integer
+
  North = -1
+
  West  = -2
+
  South = 1
+
  East  = 2
+
  None  = 0
+
End Enum
+

          
+
Class EnumSample
+
  Shared Sub Main()
+
    Dim t As Type = GetType(Direction)
+

          
+
    For i As Integer = -3 To 3
+
      ' その値は定数として宣言されているか
+
      If System.Enum.IsDefined(t, i) Then
+
          Console.WriteLine("{0} is defined in {1} as {2}.", i, t.Name, System.Enum.GetName(t, i))
+
      Else
+
          Console.WriteLine("{0} is not defined in {1}.", i, t.Name)
+
      End If
+
    Next
+
  End Sub
+
End Class
 
}}
}}
+
#tabpage-end
 

        

        
 
#prompt(実行結果){{
#prompt(実行結果){{
 
-3 is not defined in Direction.
-3 is not defined in Direction.
560,100 362,60
 
Press any key to continue
Press any key to continue
 
}}
}}
 

        

        
~
**Enum.Parse()メソッド
最後に、Parse()メソッドを用いれば、単純に文字列(または文字列化された数値)から目的の列挙型の値を取得することもできます。
+
文字列(もしくは文字列化された数値)から列挙型の値を取得するには、&msdn(netfx,method,System.Enum.Parse){Parse()メソッド};を使用します。 このメソッドでは、大文字・小文字の違いを無視するかどうかを指定することも出来ます。
 

        

        
+
#tabpage(C#)
 
#code(cs,文字列から列挙型定数の値を取得する){{
#code(cs,文字列から列挙型定数の値を取得する){{
 
using System;
using System;
 

        

        
~
// 方角を表す列挙型
namespace AboutEnumType
+
enum Direction : int
 
{
{
~
  North = -1,
    // 方角を表す列挙型
~
  West  = -2,
    enum Direction : int
+
  South =  1,
+
  East  =  2,
+
  None  =  0,
+
}
+

          
+
class EnumSample
+
{
+
  static void Main()
+
  {
+
    Type t = typeof(Direction);
+
    Direction d;
+

          
+
    // 大文字小文字を区別して"South"と名付けられた値を取得する
+
    d = (Direction)Enum.Parse(t, "South", false);
+

          
+
    Console.WriteLine(d);
+

          
+
    // 大文字小文字を無視して"north"と名付けられた値を取得する
+
    d = (Direction)Enum.Parse(t, "north", true);
+

          
+
    Console.WriteLine(d);
+

          
+
    // 指定された値から列挙型の値を取得する
+
    d = (Direction)Enum.Parse(t, "-2", true);
+

          
+
    Console.WriteLine(d);
+

          
+
    // 指定された値が見つからない場合はArgumentExceptionがスローされる
+
    try
 
    {
    {
~
      Enum.Parse(t, "南", true);
        North = -1,
-
        West  = -2,
-
        South =  1,
-
        East  =  2,
-
        None  =  0,
 
    }
    }
~
    catch (ArgumentException ex)

          
-
    // アプリケーションのエントリーポイントを提供するクラス
-
    class AboutEnumType
 
    {
    {
~
      Console.WriteLine(ex.Message);
        [STAThread]
-
        static void Main(string[] args)
-
        {
-
            Type t = typeof( Direction );
-
            Direction d;
-

          
-
            // 大文字小文字を区別して"South"と名付けられた値を取得する
-
            d = (Direction)Enum.Parse( t, "South", true );
-

          
-
            Console.WriteLine( d );
-

          
-
            // 大文字小文字を無視して"north"と名付けられた値を取得する
-
            d = (Direction)Enum.Parse( t, "north", true );
-

          
-
            Console.WriteLine( d );
-
            
-
            // 指定された値から列挙型の値を取得する
-
            d = (Direction)Enum.Parse( t, (-2).ToString(), true );
-

          
-
            Console.WriteLine( d );
-
            
-
            // 指定された値が見つからない場合はArgumentExceptionがスローされる
-
            try
-
            {
-
                Enum.Parse( t, "南", true );
-
            }
-
            catch ( ArgumentException ex )
-
            {
-
                Console.WriteLine( ex.Message );
-
            }
-
        }
 
    }
    }
+
  }
 
}
}
 
}}
}}
+
#tabpage(VB)
+
#code(vb,文字列から列挙型定数の値を取得する){{
+
Imports System
+

          
+
' 方角を表す列挙型
+
Enum Direction As Integer
+
  North = -1
+
  West  = -2
+
  South = 1
+
  East  = 2
+
  None  = 0
+
End Enum
+

          
+
Class EnumSample
+
  Shared Sub Main()
+
    Dim t As Type = GetType(Direction)
+
    Dim d As Direction
+

          
+
    ' 大文字小文字を区別して"South"と名付けられた値を取得する
+
    d = CType(System.Enum.Parse(t, "South", false), Direction)
+

          
+
    Console.WriteLine(d)
+

          
+
    ' 大文字小文字を無視して"north"と名付けられた値を取得する
+
    d = CType(System.Enum.Parse(t, "north", true), Direction)
+

          
+
    Console.WriteLine(d)
+

          
+
    ' 指定された値から列挙型の値を取得する
+
    d = CType(System.Enum.Parse(t, "-2", true), Direction)
+

          
+
    Console.WriteLine(d)
+

          
+
    ' 指定された値が見つからない場合はArgumentExceptionがスローされる
+
    Try
+
      System.Enum.Parse(t, "南", true)
+
    Catch ex As ArgumentException
+
      Console.WriteLine(ex.Message)
+
    End Try
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
 
#prompt(実行結果){{
#prompt(実行結果){{
 
South
South
663,11 425,8
 
Press any key to continue
Press any key to continue
 
}}
}}
 

        

        
~
**Enum.HasFlags()メソッド
*Flags属性を適用した列挙型
~
.NET Framework 4よりEnum.HasFlags()メソッドが追加されています。 詳細は[[programming/netfx4/System.Enum]]でまとめています。
C++では列挙型を使用せず、あらかじめ定義しておいた定数をOr演算で組み合わせて使用するという方法がよく用いられています。
+

          
+
*列挙型とフラグ
+
C++では、あらかじめ定義しておいた定数をOr演算で組み合わせて使用するという方法がよく用いられています。
 

        

        
 
#code(c,定数の組み合わせ){{
#code(c,定数の組み合わせ){{
 
#include <iostream>
#include <iostream>
697,76 456,48
 
}
}
 
}}
}}
 

        

        
~
.NET Frameworkでも、列挙型定数に対してこの例と同じようにOr演算による組み合わせの操作を行えるようになっています。 .NET Frameworkでは、このような操作を行う列挙型に対して&msdn(netfx,type,System.FlagsAttribute){FlagsAttribute};を適用することで、列挙型の値がフラグの組み合わせとして使用できることを明示出来るようになっています。
.NET Frameworkでサポートされている列挙型では、列挙型定数に対してこれと同じような操作を行えるようになっています。 それを行うためには、列挙型に対してFlagsAttributeを適用する必要があります。 この属性は列挙型に対して適用し、その列挙型の各定数が組み合わせ可能なフラグであることを明示します。 早速この属性を用いた例を見てみたいと思います。
 

        

        
+
**Flags属性を適用した列挙型
+
Flags属性は列挙型に対して適用し、その列挙型の各定数が組み合わせ可能なフラグであることを明示します。 早速この属性を用いた例を見てみたいと思います。
+

          
+
#tabpage(C#)
 
#code(cs,FlagsAttributeを適用した列挙型){{
#code(cs,FlagsAttributeを適用した列挙型){{
 
using System;
using System;
 

        

        
~
// 方角を表す列挙型
namespace AboutEnumType
+
[Flags]
+
enum Direction : int
 
{
{
~
  North = 0x00000001,
    // 方角を表す列挙型
~
  West  = 0x00000002,
    [Flags()]
~
  South = 0x00000004,
    enum Direction : int
~
  East  = 0x00000008,
    {
~
  None  = 0x00000000,
        North = 0x00000001,
~
}
        West  = 0x00000002,
~

          
        South = 0x00000004,
~
class EnumSample
        East  = 0x00000008,
~
{
        None  = 0x00000000,
~
  static void Main()
    }
~
  {

          
~
    Direction d = Direction.North | Direction.West;
    // アプリケーションのエントリーポイントを提供するクラス
~

          
    class AboutEnumType
~
    // 各定数とのAndをとってその定数が指定されているかを確かめる
    {
~
    if ((d & Direction.North) != Direction.None) Console.Write("North");
        [STAThread]
~
    if ((d & Direction.West ) != Direction.None) Console.Write("West");
        static void Main(string[] args)
~
    if ((d & Direction.South) != Direction.None) Console.Write("South");
        {
~
    if ((d & Direction.East ) != Direction.None) Console.Write("East");
            Direction d;
~

          

          
~
    Console.WriteLine();
            d = Direction.North | Direction.West;
~

          

          
~
    // d の値を直接表示
            // 各定数とのAndをとってその定数が指定されているかを確かめる
~
    Console.WriteLine(d);
            if ( ( d & Direction.North ) != Direction.None ) Console.Write( "North" );
~
  }
            if ( ( d & Direction.West  ) != Direction.None ) Console.Write( "West" );
~
}
            if ( ( d & Direction.South ) != Direction.None ) Console.Write( "South" );
~
}}
            if ( ( d & Direction.East  ) != Direction.None ) Console.Write( "East" );
~
#tabpage(VB)

          
~
#code(vb,FlagsAttributeを適用した列挙型){{
            Console.WriteLine();
~
Imports System

          
~

          
            // d の値を直接表示
~
' 方角を表す列挙型
            Console.WriteLine( d );
~
<Flags> Enum Direction As Integer
        }
~
  North = &h1
    }
~
  West  = &h2
}
+
  South = &h4
+
  East  = &h8
+
  None  = &h0
+
End Enum
+

          
+
Class EnumSample
+
  Shared Sub Main()
+
    Dim d As Direction = Direction.North Or Direction.West
+

          
+
    ' 各定数とのAndをとってその定数が指定されているかを確かめる
+
    If (d And Direction.North) <> Direction.None Then Console.Write("North")
+
    If (d And Direction.West ) <> Direction.None Then Console.Write("West")
+
    If (d And Direction.South) <> Direction.None Then Console.Write("South")
+
    If (d And Direction.East ) <> Direction.None Then Console.Write("East")
+

          
+
    Console.WriteLine()
+

          
+
    ' d の値を直接表示
+
    Console.WriteLine(d)
+
  End Sub
+
End Class
 
}}
}}
+
#tabpage-end
 

        

        
 
#prompt(実行結果){{
#prompt(実行結果){{
 
NorthWest
NorthWest
774,152 505,91
 
Press any key to continue
Press any key to continue
 
}}
}}
 

        

        
~
実行結果を見ると、先ほどのC++のコードと同様の操作を行えるようになっていることがわかります。 ただ、if文でAnd演算によって定数が指定されているかを確かめる場合、C++では条件式の値が0以外であれば真とされたのに対し、C#/VB.NETでは条件式の値はbool型とならなければならないので、C++のように簡潔な記述はできなくなっています。 そのため、値が0で何も指定されていないことを示すDirection.Noneメンバを用意しておき、これと比較する必要があります。
実行結果を見ると、先ほどのC++のコードと同様の操作を行えるようになっていることがわかります。 ただ、if文でAnd演算によって定数が指定されているかを確かめる場合、C++では条件式の値が0以外であれば真とされたのに対し、C#では条件式の値がtrueとbool型で判断されるので、C++の用に簡潔な記述はできなくなっています。 そのため、何も指定されていないことを示すDirection.Noneメンバを活用する必要があります。
 

        

        
~
**Flags属性を適用すべき/すべきでない場合
このように、Flags属性を使用すれば定数を組み合わせることは可能になるのですが、方角を表すDirection型でこのような組み合わせを可能にするのは不適当でないかと考えられます。 なぜなら次のコードのように、北と西を組み合わせた場合は北西を表すようにすることはできますが、同時に北と南のフラグを組み合わせることも可能になります。 この場合、単なる値としては問題ありませんが、意味としては無意味な値が作成されてしまいます。
+
Flags属性を適用すれば定数を組み合わせることを明示することはできますが、方角を表すDirection型でこのような組み合わせを可能にするのは不適当でないかと考えられます。 なぜなら次のコードのように、北と西を組み合わせた場合は北西を表すようにすることはできますが、同時に北と南のフラグを組み合わせることも可能になるからです。
 

        

        
+
#tabpage(C#)
 
#code(cs,無意味なフラグの組み合わせ){{
#code(cs,無意味なフラグの組み合わせ){{
~
static void Main()
[STAThread]
-
static void Main(string[] args)
 
{
{
~
  Direction d;
    Direction d;
 

        

        
~
  // 北と西を組み合わせることで、北西を表すことはできる
    // 北と西を組み合わせることで、北西を表すことはできる
~
  d = Direction.North | Direction.West;
    d = Direction.North | Direction.West;
 

        

        
~
  // ただし、方角を表すのに、北と南が同時に指定できるのは不適切
    // ただし、方角を表すのに、北と南が同時に指定されているのは不適切
~
  d = Direction.North | Direction.South;
    d = Direction.North | Direction.South;
 

        

        
~
  // それでも、単なる値としては有効
    // しかし、単なる値としては有効
~
  Console.WriteLine(d);
    Console.WriteLine( d );
 
}
}
 
}}
}}
+
#tabpage(VB)
+
#code(vb,無意味なフラグの組み合わせ){{
+
Shared Sub Main()
+
  Dim d As Direction
 

        

        
~
  ' 北と西を組み合わせることで、北西を表すことはできる
つまり、この場合のDirection型で北西のような値を表したい場合は、新たにメンバを増やした方が適切であると考えられます。 しかしながら、この方法では北北西を表す必要に迫られた場合にはさらにメンバを追加しなければならないと言う不便性もありますが、無効な組み合わせがなされる危険性を考えるとそれほど問題になりません。
+
  d = Direction.North Or Direction.West
 

        

        
+
  ' ただし、方角を表すのに、北と南が同時に指定できるのは不適切
+
  d = Direction.North Or Direction.South
+

          
+
  ' それでも、単なる値としては有効
+
  Console.WriteLine(d)
+
End Sub
+
}}
+
#tabpage-end
+

          
+
このように、単なる値としては有効ですが、意味としては無効という矛盾した値が作成されてしまう可能性があります。 よって、列挙型で北西のような値を表したい場合は、Flags属性を適用した列挙型を使用してOrによって組み合わせるのではなく、Flags属性を適用していない列挙型を使用し、新たに専用のメンバを増やした方が適切であると考えられます。
+

          
+
#tabpage(C#)
 
#code(cs,方角を適切に表現するDirection型){{
#code(cs,方角を適切に表現するDirection型){{
 
// 方角を表す列挙型
// 方角を表す列挙型
 
enum Direction : int
enum Direction : int
 
{
{
~
  North     = 1,
    North     = 1,
~
  NorthWest = 2,
    NorthWest = 2,
~
  West      = 3,
    West      = 3,
~
  SouthWest = 4,
    SouthWest = 4,
~
  South     = 5,
    South     = 5,
~
  SouthEast = 6,
    SouthEast = 6,
~
  East      = 7,
    East      = 7,
~
  NorthEast = 8,
    NorthEast = 8,
~

          

          
~
  None      = 0,
    None      = 0,
~
}
}
~
}}
}}
+
#tabpage(VB)
+
#code(vb,方角を適切に表現するDirection型){{
+
' 方角を表す列挙型
+
Enum Direction As Integer
+
  North     = 1
+
  NorthWest = 2
+
  West      = 3
+
  SouthWest = 4
+
  South     = 5
+
  SouthEast = 6
+
  East      = 7
+
  NorthEast = 8
+

          
+
  None      = 0
+
End Enum
+
}}
+
#tabpage-end
+

          
+
この方法では北北西を表す必要に迫られた場合にはさらにメンバを追加しなければならないと言う不便性もありますが、「東と北西と北北東」のような無効といえる組み合わせがなされる可能性がないことと比較するとそれほど問題にならないと思われます。
+

          
+
整理すると、Flags属性を指定するべきかどうかの判断基準は次のようになります。
+
:Flags属性を指定すべき場合|チェックボックスのように複数の項目を同時に選択することができる場合。
+
組み合わせることによって無効な値(事象)が現れないようなものを列挙型で表現する場合。
+
:Flags属性を指定すべきでない場合|ラジオボタンのように常に一つだけの項目しか選択できない場合。
+
組み合わせると無効な組み合わせが生じるものやそもそも組み合わせる必要性のないものを列挙型で表現する場合。
 

        

        
~
では、Flags属性を指定すべき列挙型にはどのようなものがあるのか、その例を見てみたいと思います。 ひとつの例として、ファイルの属性があります。 ファイルの属性には「読み取り専用、隠し、アーカイブ、システム」などの属性が存在します。 これらの属性は組み合わせることが可能で、なおかつ組み合わせによっても無効な値が生じません。
このように、Flags属性を指定するべき列挙型は、チェックボックスのように複数の項目を同時に組み合わせることができ、同時に組み合わせることによって無効な事象が現れないようなものを表現する列挙型で、ラジオボタンのように常に一つだけの値を選択させ、組み合わせると無効な組み合わせが生じる場合がある列挙型にはFlags属性を使用するべきではないといえます。
 

        

        
~
次の例は、ファイルの属性を表す列挙型であるFileAttributes列挙型を実際に作成して使用しています。 何も値が指定されていない場合、つまり属性が指定されていない場合は通常のファイルであることを示すNormalを取るようにしています。
では、Flags属性を指定すべき列挙型にはどのようなものがあるのか、その例を見てみたいと思います。 たとえば、ファイルの属性には「読み取り専用、隠し、アーカイブ、システム」などの属性が存在します。 これらの属性は組み合わせることが可能で、なおかつ組み合わせによって無効な値が生じる心配もありません。
-

          
-
次の例はファイルの属性を表す列挙型であるFileAttributes列挙型を実際に作成して使用しています。 何も値が指定されていない場合、つまり属性が指定されていない場合は通常のファイルであることを示すNormalを取るようにしています。
 

        

        
+
#tabpage(C#)
 
#code(cs,ファイルの属性を表す列挙型){{
#code(cs,ファイルの属性を表す列挙型){{
 
using System;
using System;
 

        

        
~
// ファイルの属性を表す列挙型
namespace AboutEnumType
+
[Flags]
+
enum FileAttributes : int
 
{
{
~
  ReadOnly = 0x00000001,
    // ファイルの属性を表す列挙型 
~
  Hidden   = 0x00000002,
    [Flags()]
~
  Archive  = 0x00000004,
    enum FileAttributes : int
~
  System   = 0x00000008,
    {
-
        ReadOnly = 0x00000001,
-
        Hidden   = 0x00000002,
-
        Archive  = 0x00000004,
-
        System   = 0x00000008,
 

        

        
~
  Normal   = 0x00000000,
        Normal   = 0x00000000,
~
}
    }
 

        

        
~
class EnumSample
    // アプリケーションのエントリーポイントを提供するクラス
~
{
    class AboutEnumType
~
  static void Main()
    {
~
  {
        [STAThread]
~
    // faの値はファイルから取得したとする
        static void Main(string[] args)
~
    FileAttributes fa = FileAttributes.Hidden | FileAttributes.System;
        {
~

          
            FileAttributes fa;
~
    Console.WriteLine("ファイルの属性は、{0} です。", fa);

          
~
  }
            // ファイルから属性を取得したとする
-
            fa = FileAttributes.Hidden | FileAttributes.System;
-

          
-
            // 属性を表示
-
            Console.WriteLine( "ファイルの属性は、{0} です。", fa );
-
        }
-
    }
 
}
}
 
}}
}}
+
#tabpage(VB)
+
#code(vb,ファイルの属性を表す列挙型){{
+
Imports System
+

          
+
' ファイルの属性を表す列挙型
+
<Flags> Enum FileAttributes As Integer
+
  [ReadOnly] = &h1
+
  Hidden     = &h2
+
  Archive    = &h4
+
  System     = &h8
+

          
+
  Normal     = &h0
+
End Enum
+

          
+
Class EnumSample
+
  Shared Sub Main()
+
    ' faの値はファイルから取得したとする
+
    Dim fa As FileAttributes = FileAttributes.Hidden Or FileAttributes.System
+

          
+
    Console.WriteLine("ファイルの属性は、{0} です。", fa)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
 

        

        
 
#prompt(実行結果){{
#prompt(実行結果){{
 
ファイルの属性は、Hidden, Systemです。
ファイルの属性は、Hidden, Systemです。
 
Press any key to continue
Press any key to continue
 
}}
}}
 

        

        
~
ちなみに、この例で使用したFileAttributes列挙型と同様の機能を持った列挙型がSystem.IO名前空間に存在します(&msdn(netfx,type,System.IO.FileAttributes);)。 こちらのFileAttributes型はこの例で使用したものよりも様々な属性を表すことができるようになっています。
ちなみに、この例で使用したFileAttributes列挙型と同様の機能を持った列挙型がSystem.IO名前空間に存在します。 こちらのFileAttributes型はこの例で使用したものよりも様々な属性を表すことができるようになっています。
+

          
+
**Flags属性を適用した列挙型のガイドライン
+
Flags属性を適用する場合、各メンバにどのような値を指定すべきか、またどのような名前にすべきか、などのガイドラインが&msdn(netfx,type,System.Enum){Enumクラス};および&msdn(netfx,type,System.FlagsAttribute){FlagsAttributeクラス};でまとめられています。