まさるblog

越後在住子持ちプログラマー奮闘記 - Author:まさる(高野 将、TAKANO Sho)

目次

Blog 利用状況

ニュース

著書

2010/7発売


Web掲載記事

@IT

.NET開発を始めるVB6プログラマーが知るべき9のこと

CodeZine

実例で学ぶASP.NET Webフォーム業務アプリケーション開発のポイント

第1回 3層データバインドを正しく活用しよう(前編)

ブログパーツ


書庫

日記カテゴリ

コミュニティ

任意の型で列挙体っぽい挙動をするものbeta

文字列列挙体っぽい挙動をするものbetaの続き。

 

Genericsを使って任意の型でいけるようにしました。

また、twitterで中さんから

通常Equalsはisして、==に投げる感じで

http://twitter.com/#!/nakawankuma/status/28355587110

個人的には 性別.男性と呼べればいいので、 シングルトンクラスをpublic final 性別 男性 = new 性別("1")みたいなかんじでいいかと。

http://twitter.com/#!/nakawankuma/status/28355704163

ってアドバイスいただいたので反映してみました。

 

using System;

namespace ConsoleApplication1
{
  class TypedEnum<T>
  {
    public T Value { get; private set; }

    public TypedEnum(T value)
    {
      this.Value = value;
    }

    public override string ToString()
    {
      return this.Value.ToString();
    }

    public override int GetHashCode()
    {
      return 0;
    }

    public override bool Equals(object obj)
    {
      if (obj is TypedEnum<T>)
      {
        return this.Value.Equals(((TypedEnum<T>)obj).Value);
      }
      else
      {
        return false;
      }
   }

    public static bool operator ==(TypedEnum<T> a, TypedEnum<T> b)
    {
      if (Object.Equals(a, null))
      {
        return Object.Equals(b, null);
      }
      return a.Equals(b);
    }

    public static bool operator !=(TypedEnum<T> a, TypedEnum<T> b)
    {
      if (Object.Equals(a, null))
      {
        return !Object.Equals(b, null);
      }
      return !a.Equals(b);
    }
  }

  // ISO 5218を元に作成
  class 性別 : TypedEnum<string>
  {
    private 性別(string value) : base(value) { }
    public static readonly 性別 男 = new 性別("1");
    public static readonly 性別 女 = new 性別("2");
  }

  class Program
  {
    static void Main(string[] args)
    {
      性別 sex;

      sex = 性別.男;
      Console.WriteLine("男 : {0}", sex);

      sex = 性別.女;
      Console.WriteLine("女 : {0}", sex);

      String value = sex.Value;
      Console.WriteLine("女 : {0}", value);

      Console.WriteLine("true : {0}", sex == 性別.女);
      Console.WriteLine("false : {0}", sex == 性別.男);

      Console.WriteLine("true : {0}", 性別.男 == 性別.男);
      Console.WriteLine("true : {0}", 性別.女 == 性別.女);

      Console.WriteLine("false : {0}", 性別.男 == 性別.女);
      Console.WriteLine("false : {0}", 性別.女 == 性別.男);

      Console.WriteLine("false : {0}", 性別.男 == null);
      Console.WriteLine("false : {0}", sex == null);

      Console.WriteLine("false : {0}", null == 性別.男);
      Console.WriteLine("false : {0}", null == sex);

      sex = null;
      Console.WriteLine("true : {0}", sex == null);
      Console.WriteLine("true : {0}", null == sex);
    }
  }
}

実行結果

実行結果

投稿日時 : 2010年10月22日 22:18

Feedback

# re: 任意の型で列挙体っぽい挙動をするものbeta 2010/10/22 22:32 ognac

なるほど。
奥深いものですねえ。

System.Drawing.Color構造体の要素設定も、類似かなぁ。

# re: 任意の型で列挙体っぽい挙動をするものbeta 2010/10/22 23:50 まさる

System.Drawing.Colorは構造体だから、もうちょっと簡単かもしれませんね。nullは無視していいわけだし。

# re: 任意の型で列挙体っぽい挙動をするものbeta 2010/10/23 2:18 aetos

T が参照型の場合、メンバを変更できてしまうのが難点ですね。
immutable の言語サポートがないので。

# re: 任意の型で列挙体っぽい挙動をするものbeta 2010/10/23 4:32 れい

私ならoperator==とoperator!=をObject.Equals(a,b)に投げますね。

コードが短い方がいい。
operatorに対応してない言語のこととか。
呼び出しのツリーを考えるとそれの方がシンプルかと。

# re: 任意の型で列挙体っぽい挙動をするものbeta 2010/10/23 12:59 よねけん

汎用化するなら構造体のことも意識して、IEquatable<T>インタフェースの実装もしておきたいですね。
IEquatable<T>のbool Equals(T other)メソッドを実装し、Objectのbool Equals(object obj)も演算子の==、!=もこれに委譲します。

後、GetHashCodeメソッドの実装は0を返すのではなく、
this.Value.GetHashCode()を返すのがいいと思います。

# re: 任意の型で列挙体っぽい挙動をするものbeta 2010/10/23 13:03 よねけん

あぁ、おおぼけかましてました。
TypedEnumがclassなのでIEquatable<T>は実装不要ですorz

# re: 任意の型で列挙体っぽい挙動をするものbeta 2010/10/23 19:58 あおおにくん

9月の大阪わんくまで発表したのがこれっぽいです。

↓擬似Enumです
http://www48.tok2.com/home/oninonando/contents.php?section=2

タイトル
名前
Url
コメント