連載
» 2017年04月12日 05時00分 UPDATE

.NET TIPS:整数や文字列を列挙体に変換するには?[C#/VB]

キャストにより整数を列挙体値へ変換する方法と、EnumクラスのTryParse/Parse/IsDefinedメソッドにより文字列を列挙体値へ変換する方法を説明する。

[山本康彦,BluewaterSoft/Microsoft MVP for Windows Development]
「.NET TIPS」のインデックス

連載目次

 本稿では、列挙体(または列挙型)の列挙子(あるいは列挙メンバー)に該当する整数や文字列から、列挙体の値(=列挙値)に変換する方法を解説する。

 なお、列挙体の基本となるEnumクラス(System名前空間)は.NET Frameworkの最初からあるものだが、本稿はそれ以降の内容も含んでいる。サンプルコードをそのまま試すには、Visual Studio 2015(またはそれ以降)が必要である。

整数や文字列を列挙体に変換するには?

 整数を列挙体に変換するには、キャストすればよい。

 文字列を列挙体に変換するには、EnumクラスのTryParseメソッド/Parseメソッドを使う。

 変換後の値が列挙子の1つになることを保証するには、EnumクラスのIsDefinedメソッドで確認する。

整数を列挙体に変換する例

 実際にサンプルコードで確かめてみよう。

 次のコードは、整数を列挙体に変換するコンソールアプリだ。列挙子に該当する整数と該当しない整数をそれぞれキャストする例と、キャストする前にIsDefinedメソッドで確認する方法を示している。

 列挙子に該当しない整数もキャストできてしまうので、動作するデバイス内で完結するアプリはともかくとして、Webアプリ(ASP.NET)などではIsDefinedメソッドを使った確認は必須といえるだろう。

using System;
using static System.Console;

class Program
{
  enum Era { 明治, 大正, 昭和, 平成, };

  static void Main(string[] args)
  {
    // 整数値は列挙体にキャストできる
    Era e1 = (Era)2;
    WriteLine($"2→{e1}");
    // 出力:2→昭和

    // 列挙子にない値でもキャストできてしまう
    Era e2 = (Era)4;
    WriteLine($"4→{e2}");
    // 出力:4→4

    // 列挙子に該当する値だけに制限したいときはIsDefinedメソッドで確認する
    int n = 3;
    if (Enum.IsDefined(typeof(Era), n))
    {
      Era e3 = (Era)n;
      WriteLine($"{n}→{e3}");
      // 出力:3→平成
    }
    int m = 4;
    if (!Enum.IsDefined(typeof(Era), m))
    {
      WriteLine($"{m}はEraの列挙子に該当しません");
      // 出力:4はEraの列挙子に該当しません
    }

#if DEBUG
    ReadKey();
#endif
  }
}

Option Strict On
Imports System.Console

Module Module1

  Enum Era
    明治
    大正
    昭和
    平成
  End Enum

  Sub Main()
    ' 整数値は列挙体にキャストできる
    Dim e1 As Era = CType(2, Era)
    WriteLine($"2→{e1}")
    ' 出力:2→昭和

    ' 列挙子にない値でもキャストできてしまう
    Dim e2 As Era = CType(4, Era)
    WriteLine($"4→{e2}")
    ' 出力:4→4

    ' 列挙子に該当する値だけに制限したいときはIsDefinedメソッドで確認する
    Dim n As Integer = 3
    If ([Enum].IsDefined(GetType(Era), n)) Then
      Dim e3 As Era = CType(n, Era)
      WriteLine($"{n}→{e3}")
      ' 出力:3→平成
    End If
    Dim m As Integer = 4
    If (Not [Enum].IsDefined(GetType(Era), m)) Then
      WriteLine($"{m}はEraの列挙子に該当しません")
      ' 出力:4はEraの列挙子に該当しません
    End If

#If DEBUG Then
    ReadKey()
#End If
  End Sub
End Module

整数を列挙体に変換するコンソールアプリの例(上:C#、下:VB)
このVBのコードは冒頭に「Option Strict On」を指定しているので、CTypeメソッドを使った明示的なキャストが必要だ。「Option Strict Off」(既定値)であれば、CTypeメソッドは不要である。また、Enumクラスのメソッドを呼び出すとき、VBでは「Enum」を角かっこで囲む必要がある。
C#コードの冒頭から2行目にある「using static System.Console;」という書き方は、Visual Studio 2015からのものだ。詳しくは、「.NET TIPS:構文:クラス名を書かずに静的メソッドを呼び出すには?[C# 6.0]」をご覧いただきたい。同様な機能がVBには以前から備わっており、「.NET TIPS:VB.NETでクラス名を省略してメソッドや定数を利用するには?」で解説している。
また、WriteLineメソッドに出てくる先頭に「$」記号が付いた文字列については、「.NET TIPS:数値を右詰めや0埋めで文字列化するには?[C#、VB]」の後半(「C# 6.0/VB 14で追加された補間文字列機能を使用する」)を見てほしい。
「Main」メソッド末尾にReadKeyメソッドを置く意味は、「.NET TIPS:Visual Studioでコンソール・アプリケーションのデバッグ実行時にコマンド・プロンプトを閉じないようにするには?」をご覧いただきたい。

 なお、上のコード中のEra列挙体は、以降のサンプルコードでも使用する。

TryParseメソッドで文字列を列挙体に変換する例

 .NET Framework 4からは、EnumクラスのTryParseメソッドが利用できる。変換できる文字列は、列挙子の名前と、整数の数字だ。

 なお、列挙子に該当しない整数の数字も変換されるので注意してほしい(それを避けるには、前述の整数の例と同様にIsDefinedメソッドで確認する)。

// TryParseメソッドで文字列を変換する(.NET 4から)
Era e5;
if(Enum.TryParse<Era>("大正", out e5))
  WriteLine($"「大正」→{e5}");
  // 出力:「大正」→大正
if (!Enum.TryParse<Era>("江戸", out e5))
  WriteLine($"「江戸」はEraの列挙子に該当しません");
  // 出力:「江戸」はEraの列挙子に該当しません

// 整数の数字も変換できる(列挙子に該当しない整数も変換されるので注意)
if (Enum.TryParse<Era>("2", out e5))
  WriteLine($"「2」→{e5}");
  // 出力:「2」→昭和
if (Enum.TryParse<Era>("4", out e5))
  WriteLine($"「4」→{e5}");
  // 出力:「4」→4
if (!Enum.TryParse<Era>("3.0", out e5)) // 小数点数は変換できない
  WriteLine($"「3.0」はEraの列挙子に該当しません");
  // 出力:「3.0」はEraの列挙子に該当しません

' TryParseメソッドで文字列を変換する(.NET 4から)
Dim e5 As Era
If ([Enum].TryParse(Of Era)("大正", e5)) Then
  WriteLine($"「大正」→{e5}")
  ' 出力:「大正」→大正
End If
If (Not [Enum].TryParse(Of Era)("江戸", e5)) Then
  WriteLine($"「江戸」はEraの列挙子に該当しません")
  ' 出力:「江戸」はEraの列挙子に該当しません
End If

' 整数の数字も変換できる(列挙子に該当しない整数も変換されるので注意)
If ([Enum].TryParse(Of Era)("2", e5)) Then
  WriteLine($"「2」→{e5}")
  ' 出力:「2」→昭和
End If
If ([Enum].TryParse(Of Era)("4", e5)) Then
  WriteLine($"「4」→{e5}")
  ' 出力:「4」→4
End If
If (Not [Enum].TryParse(Of Era)("3.0", e5)) Then ' 小数点数は変換できない
  WriteLine($"「3.0」はEraの列挙子に該当しません")
  ' 出力:「3.0」はEraの列挙子に該当しません
End If

TryParseメソッドで文字列を列挙体に変換する例(上:C#、下:VB)

 なお、カンマで区切った文字列を与えることもできる(次のコード)。これはフラグ列挙体(=Flag属性を付けた列挙体)の場合には望ましい動作だが、通常の列挙体でも同じ動作なので、注意していないと思わぬ結果になるかもしれない。これを避けるには、やはりIsDefinedメソッドで確認する(その例は次のParseメソッドで示す)。

Era e5;
// カンマ区切りで渡すと、bitごとのOR演算の結果で列挙値に変換される
if (Enum.TryParse<Era>("明治, 大正", out e5))
  WriteLine($"「明治, 大正」→{e5}"); // 0000 | 0001 → 0001
  // 出力:「明治, 大正」→大正
if (Enum.TryParse<Era>("大正, 昭和", out e5))
  WriteLine($"「大正, 昭和」→{e5}"); // 0001 | 0010 → 0011
  // 出力:「大正, 昭和」→平成

Dim e5 As Era
' カンマ区切りで渡すと、bitごとのOR演算の結果で列挙値に変換される
If ([Enum].TryParse(Of Era)("明治, 大正", e5)) Then
  WriteLine($"「明治, 大正」→{e5}") ' 0000 Or 0001 → 0001
  ' 出力:「明治, 大正」→大正
End If
If ([Enum].TryParse(Of Era)("大正, 昭和", e5)) Then
  WriteLine($"「大正, 昭和」→{e5}") ' 0001 Or 0010 → 0011
  ' 出力:「大正, 昭和」→平成
End If

カンマ区切りの文字列を列挙体に変換する例(上:C#、下:VB)
なお、カンマ区切りの文字列を変換したくないときは、IsDefinedメソッドで確認する。ただしその場合は、変換できると分かっているのだからTryParseメソッドを使う必要がない(Parseメソッドでよい)。

Parseメソッドで文字列を列挙体に変換する例

 .NET Framework 4以前は、EnumクラスのParseメソッドを使う。変換できない文字列を与えたときは例外が出るので、try〜catchするか、事前にIsDefinedメソッドで確認する(次のコード)。

// .NET 4以前はParseメソッド
WriteLine($"「大正」→{Enum.Parse(typeof(Era),"大正")}");
// 出力:「大正」→大正
try
{
  WriteLine($"「江戸」→{Enum.Parse(typeof(Era), "江戸")}");
}
catch (Exception ex)
{
  WriteLine($"「江戸」→{ex.GetType().Name}");
  // 出力:「江戸」→ArgumentException
}
WriteLine($"「3」→{Enum.Parse(typeof(Era), "3")}");
// 出力:「3」→平成

// Parseメソッドも、カンマ区切りの文字列に対応
WriteLine($"「大正, 昭和」→{Enum.Parse(typeof(Era), "大正, 昭和")}");
// 出力:「大正, 昭和」→平成

// カンマ区切りの文字列を避けるにはIsDefinedメソッドで確認する(TryParseメソッドも同様)
string s1 = "昭和";
if (Enum.IsDefined(typeof(Era), s1))
  WriteLine($"「{s1}」→{Enum.Parse(typeof(Era), s1)}");
  // 出力:「昭和」→昭和
string s2 = "大正, 昭和";
if (!Enum.IsDefined(typeof(Era), s2))
  WriteLine($"「{s2}」はEraの列挙子に該当しません");
  // 出力:「大正, 昭和」はEraの列挙子に該当しません

' .NET 4以前はParseメソッド
WriteLine($"「大正」→{[Enum].Parse(GetType(Era), "大正")}")
' 出力:「大正」→大正
Try
  WriteLine($"「江戸」→{[Enum].Parse(GetType(Era), "江戸")}")
Catch ex As Exception
  WriteLine($"「江戸」→{ex.GetType().Name}")
  ' 出力:「江戸」→ArgumentException
End Try
WriteLine($"「3」→{[Enum].Parse(GetType(Era), "3")}")
' 出力:「3」→平成

' Parseメソッドも、カンマ区切りの文字列に対応
WriteLine($"「大正, 昭和」→{[Enum].Parse(GetType(Era), "大正, 昭和")}")
' 出力:「大正, 昭和」→平成

' カンマ区切りの文字列を避けるにはIsDefinedメソッドで確認する(TryParseメソッドも同様)
Dim s1 As String = "昭和"
If ([Enum].IsDefined(GetType(Era), s1)) Then
  WriteLine($"「{s1}」→{[Enum].Parse(GetType(Era), s1)}")
  ' 出力:「昭和」→昭和
End If
Dim s2 As String = "大正, 昭和"
If (Not [Enum].IsDefined(GetType(Era), s2)) Then
  WriteLine($"「{s2}」はEraの列挙子に該当しません")
  ' 出力:「大正, 昭和」はEraの列挙子に該当しません
End If

Parseメソッドで文字列を列挙体に変換する例(上:C#、下:VB)

まとめ

 整数を列挙体に変換するにはキャストすればよい。文字列(整数の数字か列挙子の名前)を列挙体に変換するには、EnumクラスのTryParseメソッド(.NET 4から)/Parseメソッド(.NET 4以前)を使う。いずれも、列挙子が定義されているものだけに厳密に変換したいときは、EnumクラスのIsDefinedメソッドでチェックする。

「.NET TIPS」のインデックス

.NET TIPS

Copyright© 1999-2017 Digital Advantage Corp. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。