R.Tanaka.Ichiro's Blog

主にC# な話題です

目次

Blog 利用状況

ニュース

enum のオブジェクト化

先日、うちの会社に持ち込まれたコードを眺めていたら、大量に enum と switch が使われていました。
僕は、何でもオブジェクトにするので

enum と switch 文

を書くことが殆どありません。

しかし、人の書いたコードを見ると、思った以上に enum やswitch 文の使用が目立ちます。

例えば、次の2つの記述パターンがあった時、僕は迷わず後者を選択します。
皆さんは、どちらの方法を使いますか?


~enum と switch による処理~

enum Signal { Red, Blue, Yellow };
class Hoge {
  public void Fuga() {
    var signal = Signal.Red;
    DisplayTitle(signal);
    Action(signal);
  }

  public void DisplayTitle(Signal signal){
    switch(signal) {
      case Siglal.Red:  Console.WriteLine("赤"); break;
      case Signal.Blue:  Console.WriteLine("青"); break;
      case Signal.Yellow: Console.WriteLine("黄"); break;
    }
  }

  public void Action(Signal signal){
    switch(signal) {
      case Siglal.Red:  Console.WriteLine("急いで進む"); break;
      case Signal.Blue:  Console.WriteLine("堂々と進む"); break;
      case Signal.Yellow: Console.WriteLine("注意して進む"); break;
    }
  }
}


~object 化~ 

class Hoge {
  void Fuga() {
    var signal = Signal.Blue;
    signal.DisplayTitle();
    signal.Action();
  }
}

class Signal {
  public string Name { get; protected set; }
  public string Title { get; protected set; }
  public virtual void Action() {}
  public void DisplayTitle() { Console.WriteLine(this.Title); }

  private static Signal _Red = new SignalRed();
  public static Signal Red{ get{ return _Red; }}

  private static Signal _Yellow = new SignalYellow();
  public static Signal Yellow { get{ return _Yellow; }}

  private static Signal _Blue = new SignalBlue();
  public static Signal Blue{ get{ return _Blue; }}
}

class SignalRed : Signal {
  public SignalRed() {
    this.Name = "Red";
    this.Title = "赤";
  }
  public override void Action() {
    Console.WriteLine("急いで進む");
  }
}

class SignalYellow : Signal {
  public SignalYellow() {
    this.Name = "Yellow";
    this.Title = "黄";
  }
  public override void Action() {
    Console.WriteLine("注意して進む");
  }
}

class SignalBlue : Signal {
  public SignalBlue() {
    this.Name = "Blue";
    this.Title = "青";
  }
  public override void Action() {
    Console.WriteLine("堂々と進む");
  }
}

投稿日時 : 2009年7月3日 16:33

Feedback

# re: enum のオブジェクト化 2009/07/03 17:05 かるあ

これは、つりだよなーと思いながら。。。

使う側はenumのインテリセンスが聞いてくれる分、前者の方がわかりやすい気もする。

# re: enum のオブジェクト化 2009/07/03 18:27 画伯

例のまま「信号機」でいくと,流動的要素がないので上を採用。流動的要素を持つ別のものである場合は下を採用。

あっ,でも歩行者用信号(青 → 青点滅 →赤)とか考えると流動的といえば流動的・・・?

え?私が真面目にコメントしちゃダメだって言うんですか?!

# re: enum のオブジェクト化 2009/07/03 18:40 えムナウ

Rさんは static プロパティの get 時にいちいち new をするそうだ。

# re: enum のオブジェクト化 2009/07/03 23:07 れい

これ、もう15年以上悩みの種なんですが。
ほんとにわからない。

使い分けの指針をだれか教えてください。


# re: enum のオブジェクト化 2009/07/04 0:26 irxn

もちろん、これで!
enum Signal {
Red("赤", "急いで進む"),
Yellow("黄","注意して進む"),
Blue("青", "堂々と進む");

public final String color, action;
public Signal(String color, String action) {
this.color = color;
this.action = action;
}
}

# re: enum のオブジェクト化 2009/07/04 10:14 もり ひろゆき

私の場合、ずばり、ケースバイケースでしょうねぇ(^^;

こういうネタは話し出すと長くなるので、ここらへんで(^^;;;;

# re: enum のオブジェクト化 2009/07/04 21:11 渋木宏明(ひどり)

基本、場合によりけりです>じぶん

僕も switch ~ case は使わない派なので、手っ取り早く前者と等価なコードが欲しい時は

enum Signal { Red = 0, Blue = 1, Yellow = 2 }

var actions = new Dictionary<Signal, Func<Signal>>
{
{ Red, (Func<Signal>) _ => Console.WriteLine("赤") },
{ Blue, (Func<Signal>) _ => Console.WriteLine("青") },
{ Yellow, (Func<Signal>) _ => Console.WriteLine("黄") },
}

みたいなカンジ。で、これで困るようなら、その時点でリファクタリング。

将来的な展望があるならともかく、その時点での必要性に疑問符が点灯するような状態では、クラスは導入したくないかなーという今日この頃です。(クラスを維持するのにもコストかかるし)

>使い分けの指針をだれか教えてください。

条件はイロイロあるから、汎用的な指針を編み出すのは難しいでしょうね。

僕の中では、扱うものの「量」や「種類」に注目する時

・たった1つ
・2択
・3つ以上のどれか

で方針を切り替えるようにしています。

「将来」として見据えるスパンは、最長でも「次のバージョンアップ」です。

それ以上先の未来なんか予測しても、容易に覆るので。

# re: enum のオブジェクト化 2009/07/05 14:39 R・田中一郎

かるあ さん

>使う側はenumのインテリセンスが聞いてくれる分、前者の方がわかりやすい気もする。

後者もインテリセンスに候補があがると思ふ。

----------------------------------------
画伯 さん

>例のまま「信号機」でいくと,流動的要素がないので上を採用。流動的要素を持つ別のものである場合は下を採用。

ひょっとして、後日、Green を Blue と同じ扱うにするかもしれません。

>あっ,でも歩行者用信号(青 → 青点滅 →赤)とか考えると流動的といえば流動的・・・?

信号の電源が落ちている状態が必要になるやもしれません。

----------------------------------------
えムナウ さん

>Rさんは static プロパティの get 時にいちいち new をするそうだ。

ちょっと行数ケチろうとしたんですけど、やっぱり突っ込まれてしまった orz
・・・ということで修正しました。

----------------------------------------
れい さん

>使い分けの指針をだれか教えてください。

悩ましいのでオブジェクトオンリーにしちゃった僕が前を通ります。

----------------------------------------
irxn さん

>もちろん、これで!

動かないのですが。

----------------------------------------
もり ひろゆき さん

>こういうネタは話し出すと長くなるので、ここらへんで(^^;;;;

何だろう、みんなのあっさり感は・・・

----------------------------------------
渋木宏明(ひどり) さん

>僕も switch ~ case は使わない派なので、手っ取り早く前者と等価なコードが欲しい時は

オブジェクトとメンバの、どちらが流動的なのかによるケース・バイ・ケースってことですよね。
列挙型に限らず、全ての設計に言えることなのかなぁ、とも思います。

# re: enum のオブジェクト化 2009/07/05 16:47 irxn

ごめんなさい。Javaと勘違いしていました。そして、Javaでも私のソースが間違っていて、コンストラクタはprivateでないといけません。でもJavaのenumは沢山のSingleton(沢山なのにSingleとは)が作れて好きです。

# re: enum のオブジェクト化 2009/07/05 17:09 R・田中一郎

なるほど、すっきりしました。
Java の enum は便利なんですねぇ。

# re: enum のオブジェクト化 2009/07/13 13:11 かずき

乗り遅れ~。
Javaには昔enumが無かったので、Rさんのしてるのと同じことをして、Typesafe enum patternとして広く?使われていました。
(おかげでenumをうけとる べきところをintで受け取るAPIがいっぱい)

あるときJavaがバージョンアップをする際に、Typesafe enum patternと等価なコードをenumキーワードで掛けるようにしたそうじゃ。
そんなことが昔ありました。

# re: enum のオブジェクト化 2009/07/13 15:11 R・田中一郎

設計としてクラスにすべきか、enum と switch で回すかを選択できるという点では良いことなんでしょうね。

タイトル
名前
Url
コメント