C#でEnum型用の拡張メソッドを作ってみた

JavaだとEnumの中にかけるから、基底Enum作って継承すれば良いんだけどさ。不便よね、もうw

C#やVBでのEnum型って所詮は Int だらけの構造体w<やめい

なので、汎用的にごにょりたいときは拡張メソッド使うw

使うEnum型はこういうの。

public enum ColorDefine
{
    [Description("不明")]
    None = 0,

    [Description("緑")]
    Green = 1,

    [Description("赤")]
    Red = 2,

    [Description("青")]
    Blue = 3,

    [Description("黄")]
    Yellow = 4
}

このEnumに日本語名称をつけて、これを拡張メソッドで取れるようにする。

public static string GetProperName<T>(this T Value) 
{
    if (!(typeof(T).IsEnum))
    {
        throw new InvalidEnumArgumentException();
    }

    FieldInfo fieldInfo = Value.GetType().GetField(Value.ToString());
    if (fieldInfo == null) return null;

    var attr = (DescriptionAttribute)fieldInfo.GetCustomAttribute(typeof(DescriptionAttribute));
    if (attr == null) return "";
    return attr.Description;
}

といいつつ、この拡張メソッドはすべての型に適用可能になっててインテリセンスにも出てくる。使っちゃうと例外かっとぶのでそれはそれで問題。なのでEnum型に絞ることを考えてみる。

まぁ、Whereで制約をつければ良いんだけどね。

https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters

image

じゃぁ、Enum型にはどの制約をつければいいのか、って時に、Docs大事。

https://docs.microsoft.com/ja-jp/dotnet/api/system.enum?view=netstandard-2.0

image

この記載をみれば、Where定義に何を書けばいいのかが判る。

ちな、ValueTypeはWhere定義では叱られるけど、ここは値型のstructでOK。だって所詮はInt型の(ry。というわけでリファクタリング。

public static string GetProperName<T>(this T Value) 
    where T : struct, IComparable, IConvertible, IFormattable
{
    if (!(typeof(T).IsEnum))
    {
        throw new InvalidEnumArgumentException();
    }

    FieldInfo fieldInfo = Value.GetType().GetField(Value.ToString());
    if (fieldInfo == null) return null;

    var attr = (DescriptionAttribute)fieldInfo.GetCustomAttribute(typeof(DescriptionAttribute));
    if (attr == null) return "";
    return attr.Description;
}

制約入れたのに、まだEnum型かどうかのチェックをしているのは、Enum型が所詮は Int の列挙型にすぎないので、この制約でもInt型変数に対してメソッドが使用可能となるから。なのでそれもあわせてテストに書いて

[Test, Sequential]
public void GetProperNameColorDefine([Values]ColorDefine prm1,
                          [Values("不明", "緑", "赤","青","黄")] string exp1)
{
    var act = Extenstions.GetProperName(prm1);
    Assert.AreEqual( exp1, act);
}
[Test]
public void GetProperNameColorDefineException()
{
    int Err = 200;
    Assert.Throws<InvalidEnumArgumentException>(() => Err.GetProperName());
}

実行したら

image

グリーンだよv