2012年7月18日水曜日

[C#]Enumに振る舞いを

Enumにプロパティとかメソッドとか、豊富な振る舞いを持たせたい時どうすればいいんだろうという疑問です。

拡張メソッドを使う

public enum AircraftType
{
    Fighter,
    Attacker,
    Bomber
}

public static class AircraftTypeHelper
{
    public static string DisplayName(this AircraftType value)
    {
        return _displayNames[value];
    }

    private readonly static IDictionary<AircraftType, string> _displayNames = new Dictionary<AircraftType, string>()
    {
        { AircraftType.Fighter, "戦闘機" },
        { AircraftType.Attacker, "攻撃機" },
        { AircraftType.Bomber, "爆撃機" }
    };
}
 string displayName = AircraftType.Fighter.DisplayName();

こんな感じに拡張メソッドを使うと、プロパティは無理だけど、それなりに振る舞いをつけることができます。

素直にクラスで実装する

public class AircraftType
{
    private AircraftType(AircraftTypeValue value)
    {
        value = value;
    }

    private enum AircraftTypeValue
    {
        Fighter,
        Attacker,
        Bomber
    }

    public static readonly AircraftType Fighter = new AircraftType(AircraftTypeValue.Fighter);
    public static readonly AircraftType Attacker = new AircraftType(AircraftTypeValue.Attacker);
    public static readonly AircraftType Bomber = new AircraftType(AircraftTypeValue.Bomber);

     private readonly AircraftTypeValue _value;

    public override bool Equals(object obj)
    {
        var other = obj as AircraftType;
        return other != null && _value == other._value;
    }

    public override int GetHashCode()
    {
        return _value.GetHashCode();
    }

    public override string ToString()
    {
        return _value.ToString();
    }
}

こんな感じでシングルトンで実装する方法です。Equals とか ToString なんかの基本的なメソッドの実装は内部に隠してある Enum に丸投げ。

これならプロパティでもなんでも追加できます。(当たり前だけど...)

    public string DisplayName
    {
        get { return _displayNames[_value]; }
    }

    private readonly static IDictionary<AircraftTypeValue, string> _displayNames = new Dictionary<AircraftTypeValue, string>()
    {
        { AircraftTypeValue.Fighter, "戦闘機" },
        { AircraftTypeValue.Attacker, "攻撃機" },
        { AircraftTypeValue.Bomber, "爆撃機" }
    };
    string displayName = AircraftType.Fighter.DisplayName;

どっちがいいんだろう

拡張メソッドを使う方はまんま Enum を使うので手軽ですね。でも拡張メソッド以上のことはできないので、複雑な振る舞いを持たせたりするのには向いていないですね。

シングルトンでの実装は、自由にプロパティでもメソッドでも追加できるので柔軟性はあります。でも、実装がちょっと面倒です。

また、Enum をそのまま使うと FlagsAttributes でビット演算できたりして重宝することもあります。

個人的には後者(シングルトン)を使うことが多いのですが、振る舞いなんかがあまりない純粋な列挙値だったら普通に Enum を使います。あと、ビット演算したいときとか…

ケース・バイ・ケースなのかな?

0 件のコメント:

コメントを投稿

TFT 10.14 Peeba Comp

こちらのガイドの自分用まとめです。 https://www.reddit.com/r/CompetitiveTFT/comments/hraunp/tft_1014_break_the_meta_new_peeba_comp_set_35/ 難しいですが完成すると非常に強く、プレ...