52
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

文字列から enum 型への安全な変換

Last updated at Posted at 2017-11-15

文字列からの変換

文字列を数値型とか enum 型とかに変換する場合、Parse() とか TryParse() を使うかと思います。

Parse() は、成功すれば変換された値が返ってくる点は楽なのですが、失敗したときに例外を吐くので少々扱いにくいです。

一方、TryParse() のシグネチャは bool TryParse(string s, out T v) となっています。返り値は解釈成功・失敗を表し、変換された値は v に入ります。変数 v を事前に宣言する1面倒くささはありますが、失敗したときの処理は簡単です。

enum 型への変換

enum 型には、bool Enum.TryParse<TEnum>(string s, out TEnum e) が使えます。
名前からでも数字からでも TEnum 型に変換できます。

enum Weekday {
  Sunday = 0,
  Monday = 1,
  Tuesday = 2,
    :
  Saturday = 6
}

Weekday wd;
Enum.TryParse("2", out wd); // true, wd = Weekday.Tuesday
Enum.TryParse("Friday", out wd ); // true, wd = Weekday.Friday
Enum.TryParse("April", out wd); // false, wd = ?

ところが、数字からの変換が曲者で、enum 型で定義していない値でも変換に成功したことにして outの変数に入れてしまいます。

Enum.TryParse("100", out wd); // true, wd = 100

enum 型への安全な変換

ある値が enum 型で定義されているか検証するには、Enum.IsDefined() を使います。これを TryParse() と組み合わせれば、安全な変換が実現できます。

static class EnumExt
{
  static bool TryParse(string s, out Weekday wd)
  {
    return Enum.TryParse(s, out wd) && Enum.IsDefined(typeof(Weekday), wd);
  }
}

EnumExt.TryParse("100", out wd); // false, wd = 100

任意の enum 型に対応するため、ジェネリック化します。
型パラメータ TEnum は enum 型のみを許容するので、'where` 節で制約します。

static class EnumExt
{
  static bool TryParse<TEnum>(string s, out TEnum wd) where TEnum : struct
  {
    return Enum.TryParse(s, out wd) && Enum.IsDefined(typeof(TEnum), wd);
  }
}

Weekday wd;
EnumExt.TryParse("Thursday", out wd); // true, wd = Weekday.Thursday
SolarSystem ss; // Sun=0, Mercury, Venus, ...
EnumExt.TryParse("5", out ss); // true, ss = SolarSystem.Jupiter

残課題

  • : struct は、TEnum を値型に制約しています。できれば enum 型に制約したいのですが、enum 型はクラスではないのでできません。
  • 作成した TryParse は自作クラスのメンバになります。できれば Enum 型の拡張メソッドにしたいのですが、静的メソッドで this を引数にできないので、拡張メソッドにはできません。
  1. C# 7 では、事前の宣言が不要になるようです。

52
37
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
52
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?