R.Tanaka.Ichiro's Blog

主にC# な話題です

目次

Blog 利用状況

ニュース

列挙型を使う(その4)

列挙型を使う
http://blogs.wankuma.com/rti/archive/2007/03/12/66244.aspx

列挙型を使う(その2)
http://blogs.wankuma.com/rti/archive/2007/03/13/66420.aspx

列挙型を使う(その3)
http://blogs.wankuma.com/rti/archive/2007/03/14/66719.aspx

の続きです。

例えば、C# によって以下のような列挙型を指定したとします。


enum 血液型 { A, B, O }


この血液型という列挙型は、血液型として取り扱えるため、つい「A, B」という値として取り扱ってしまい、実際には int 型 で取り扱われていることを、忘れてしまいそうになります。

そんな状態で、例えば、コンボボックスなどで選択した血液型の結果の値を、データベースの「カルテ」という名のテーブルに格納したとします。

その後、先ほどの血液型の「A」と「B」の間に 「AB」型を加えた(あるいは、並べ替えた)とします。


enum 血液型 { A, AB, B, O }


しかし、カルテテーブルには数値で登録されているため、例えば、今まで O 型の血液型とされていた人が B 型として取り扱われることになってしまいます。

これは、とっても

恐ろしい

ことです。

さて、性格と称する列挙型を設けたとします。


enum 性格 { A, B, O, AB, 理解不能 }


性格は、最初からわからないので、初期値を先ほどの血液型の値から設定することにします。


性格 x = (性格)血液型.O;


 しかし、よく見ると列挙されている内容の並びが血液型と性格で異なってしまっています。
これによって、x は AB の値が登録されることになります。

また、以下のような書き方も、混乱を招きます。


if (性格.B.Equals(血液型.B)) {
  return "この人は、血液型通り B型な性格のようです。";
}


列挙型は、内容が直感的にわかるため便利ではありますが、実際には対応する値を持ち、この値が実体であるということを常に念頭におく必要がある点に注意して下さい。

投稿日時 : 2007年3月15日 13:45

Feedback

# re: 列挙型を使う(その4) 2007/03/15 13:51 R・田中一郎

ちなみに、血液型による性格分類を信じている訳ではないです。

# re: 列挙型を使う(その4) 2007/03/15 13:56 中博俊

void func(血液型 val)

にたいして、

func((血液型)100)

どうやってチェックしますかー

# re: 列挙型を使う(その4) 2007/03/15 18:45 黒龍

あ~我慢できない~ん
if(!Enum.IsDefined(typeof(血液型), data))
  throw new ArgumentException();

# re: 列挙型を使う(その4) 2007/03/15 18:46 黒龍

ぐはぁ失敗
if(!Enum.IsDefined(typeof(血液型), val))
throw new ArgumentException();

# re: 列挙型を使う(その4) 2007/03/15 18:47 梅林

本来enumなプロパティへのセットやメソッドのパラメータは

if (!Enum.IsDefined(typeof(血液型), val))
{
throw new InvalidEnumArgumentException(val, (int)val, typeof(血液型));
}

みたいにチェックしないといけないんですよね。
(サボってあまり実践していませんが)

# re: 列挙型を使う(その4) 2007/03/15 18:53 梅林

う、黒龍さんとかぶってしまった。
でもこれって、コンパイル時にエラーにしようと思えばできそうな気がするんですけどね。

# re: 列挙型を使う(その4) 2007/03/15 18:56 梅林

間違い発見

>if (!Enum.IsDefined(typeof(血液型), val))
>{
>throw new InvalidEnumArgumentException(val, (int)val, typeof(血液型));
>}

if (!Enum.IsDefined(typeof(血液型), val))
{
throw new InvalidEnumArgumentException('val', (int)val, typeof(血液型));
}

ですね。

# re: 列挙型を使う(その4) 2007/03/15 20:56 中博俊

きみたち、明日の田中さんのネタをとっちゃダメーよ!!
おしおきだべぇ

# re: 列挙型を使う(その4) 2007/03/16 10:21 R・田中一郎

黒龍 さん

>あ~我慢できない~ん

>ぐはぁ失敗

ちょwwwおまwwww

-----------------------------------------------
梅林 さん

>でもこれって、コンパイル時にエラーにしようと思えばできそうな気がするんですけどね。

kwsk

-----------------------------------------------
中博俊 さん

>きみたち、明日の田中さんのネタをとっちゃダメーよ!!

バレてましたね。

>おしおきだべぇ

この場合、ドクロベエ=中さんとして、黒龍さんと、梅林さんは、どちらがボヤッキーで、どちらがトンズラーになるのでしょうか。

http://d.hatena.ne.jp/keyword/%a5%e4%a5%c3%a5%bf%a1%bc%a5%de%a5%f3

# re: 列挙型を使う(その4) 2007/03/16 12:59 梅林

>>でもこれって、コンパイル時にエラーにしようと思えばできそうな気がするんですけどね。

>kwsk

例えば

int intVal1 = int.MaxValue + 1;
とか
int intVal2 = 99999 * 99999;

というコードはコンパイル時に

「この操作はチェックモードでコンパイルしたときにオーバーフローします」

というメッセージが表示され、コンパイルできません。


で、enumのメンバはコンパイル時に整数値に対応付けられるため

enum TestEnum {A, B, C}
TestEnum value = (TestEnum)((int)TestEnum.C + 1);

というコードも、コンパイル時にオーバーフローを認識してエラーにできると思うのです。

もちろんenumでは
enum TestEnum {A = 1, B = 10, C = 100}

みたいに飛び飛びの数値を対応付けることができるので、範囲チェックが
多少複雑かもしれませんが、いずれにしても定数式と比較する限りは
コンパイル時に解決できる問題だと思います。

# re: 列挙型を使う(その4) 2007/03/16 16:06 黒龍

>>おしおきだべぇ

>この場合、ドクロベエ=中さんとして、黒龍さんと、梅林さんは、どちらがボヤッキーで、どちらがトンズラーになるのでしょうか。
昔はボヤッキー体形でしたが最近どんどんトンズラー化してます^^;

# re: 列挙型を使う(その4) 2007/03/17 11:39 R・田中一郎

梅林 さん

>多少複雑かもしれませんが、いずれにしても定数式と比較する限りは
>コンパイル時に解決できる問題だと思います。

なるほど、これは面白いですね。
詳しいご説明をありがとうございました。

----------------------------------------------------
黒龍 さん

>昔はボヤッキー体形でしたが最近どんどんトンズラー化してます^^;

いやいや、ご謙遜を。
わんくま勉強会のビデオを見る限り、まだまだ全然ボヤッキーですよ(注意・・・これは褒め言葉です)

# 列挙型を使う(その6) 2007/03/19 10:07 R.Tanaka.Ichiro's Blog

列挙型を使う(その6)

# I'm impressed! You'v 2014/05/10 6:09 Kelis

I'm impressed! You've managed the almost imsebsiplo.

タイトル
名前
Url
コメント