VB のたまご

作成日: 2015/12/03, 更新日: 2015/12/03


既存の問題と、ジェネリックが生まれた背景を知ろう

何でもセットできることのデメリット

  •  ジェネリックと言えばジェネリック医薬品です。同じ効果があるのに低価格で購入できる庶民の味方です。 VB2005 でも、ジェネリックが採用されました。VB.NET のジェネリックは、医療のジェネリックと同じなのでしょうか?

  •  うーん、うーんと悩んでいると、知らないおじさんからツイートが流れてきました。どれどれ。
  • 「顧客名簿を管理するアプリケーションを作成してくださいなう。」

  •  はぁ、顧客名簿ですか。誰だか知りませんが、作成してみます。
  • 顧客管理となると、DB いるよなぁ。あれこれ悩んでいると、知らないおじさんからまたツイートが。
  • 「超簡単でいいですなう。UI は後回しでいいので、データの持ち方だけ先になう。」

  •  というわけで、知らないおじさんに言われた通り、仕様を考えてみます。面倒くさいし、超簡単でいいと言っているし。 考えた結果、管理番号と名前のペアで管理できる、辞書データで管理することにしました。
  • ' 辞書データ
    Dim dic1 As New Hashtable
    dic1.Add(1, "taro")
    dic1.Add(2, "jiro")
    

  •  OK。できた。完璧。

  •  さすが仕事が早いね!んじゃ、一杯飲みに行こうか。と考えていると、知らないおじさんからまたツイートが。
  • 「それだと Object 型と Object 型のペアだから、ダメですなう。名前と管理番号でも登録できちゃうなう。」

  •  知らないおじさんの言い分はこういうことみたいです。
  • ' 辞書データ
    Dim dic1 As New Hashtable
    dic1.Add(1, "taro")
    dic1.Add(2, "jiro")
    dic1.Add("hanako", 3) ' ← こういう登録の仕方をする人もおるやろがい。
    

  •  まぁ、やろうと思えばできてしまいますが、そういうのはルール決めて、周知すればいいことでしょ。 登録する際は、「管理番号、名前」の順で登録するべしと。

  •  OK。言い訳完璧!んじゃ、一杯飲みに行こうか。と考えていると、知らないおじさんからまたツイートが。
  • 「ダメですなう。厳密な型で管理してくれなきゃ、泣いちゃうなう。」

スポンサーリンク


限られたデータのみセットできることのメリット

  •  知らんがな、こっちは大事な用があんねん。と、考えようとしましたが、今までのやり取りから、 相手は思考を読む能力者でもあることを深層心理内で察知した私は、以前こんなニュースを思い出しました。

  • 「知らないおじさんから来たツイートを無視した若手プログラマー、翌日プログラムの知識だけが記憶喪失になる。」

  •  うわっ、ご都合主義なやつだ!それされるのは困るので、相手のわがままに付き合うことにしました。
  • しかし、厳密な型を指定できるリストってあるのかな?必死で探してみると、見つけました。

  •  Dictionary という型なのですが、普段と感じが違います。あー、自分で型を指定しながらインスタンス生成する使い方みたいです。 試しに、Integer 型と String 型で作ってみます。
  • Dim dic2 As New Dictionary(Of Integer, String)
    dic2.Add(1, "taro")
    dic2.Add(2, "jiro")
    'dic2.Add("hanako", 3) ' Option Strict On で 'xxx' から 'yyy' への暗黙的な変換はできません。
    

  •  これはスゴイ!管理番号には管理番号しか登録できないようになっています。 名前を入力しようものなら、コーディングエラーではじいてくれるじゃないですか!
  • 「新旧でループ処理して、値取得の比較してみななう。」


  •  興奮して、ツイートに気が付かない私。
  • あれ、以前は、値を取得する際、Object 型から任意の型に、いちいち型変換していたけど、 もしかして・・・。
  • Dim dic1 As New Hashtable
    dic1.Add(1, "taro")
    dic1.Add(2, "jiro")
    dic1.Add("hanako", 3)
    
    For Each key In dic1.Keys
        Dim number As Integer = CInt(key) ' InvalidCastException / String "hanako" から型 'Integer' への変換は無効です。
        Dim name As String = CStr(dic1(key))
        Console.WriteLine("number = {0}, name = {1}", number, name)
    Next
    

  •  以前は、このように、型変換越しに値を取得していました。ちなみに実行時にエラー発生します。 それが、今回の場合、型変換しなくても値を取得することができるようになっています。

  • Dim dic2 As New Dictionary(Of Integer, String)
    dic2.Add(1, "taro")
    dic2.Add(2, "jiro")
    
    For Each key In dic2.Keys
        Dim number As Integer = key
        Dim name As String = dic2(key)
        Console.WriteLine("number = {0}, name = {1}", number, name)
    Next
    

  •  こりゃ便利!実装が楽だ。しかも見通しも良い!
  • 「どうですなう。頑張った甲斐があったねなう。」
  •  興奮して、ツイートに気が付かない私。

  • 「おーいなう、おーいなう。」
  • 「気付けやなう。ダメみたいなう。なうなう言うのも疲れたなう。」
  • 「しょうがなう。んじゃ、ポチっとなう。」

  •  その時私は、目を疑いました。突然頭上からたらいが降ってきて、当たった瞬間に次のたらいが降ってきて。 ついには意識を失いました・・・。


  •  ・・・。は!
  • 気が付くと、ベットの中。目覚まし時計が鳴り響いていました。どうやら、夢を見ていたようです。

スポンサーリンク


ジェネリックは、クラスだけのものにあらず

  •  しかし、すごい夢でした。あのおじさんは誰だったんだろう。
  • 朝の支度を済ませます。今日は良い天気です。ただ、夢の内容で、気になっていたことがありました。 それは、ジェネリックが任意の型を自由に指定できる、というポイントです。 Dictionary はクラスでしたが、メソッドにも同じようにできるのかな?という推測です。

  •  その後、あっという間に夕方になっていました。
  • 推測は当たり、ジェネリックメソッドというものがあることが分かり、せっかくなので自作に挑戦しました。
  • Me.GetTypeInfo(Of Integer)(5)
    Me.GetTypeInfo(Of Decimal)(10D)
    
    Private Sub GetTypeInfo(Of T)(value As T)
    
        Dim defaultValue As T = CType(Nothing, T)
        Console.WriteLine("type = {0}, defaultValue = {1}, value = {2}", value.GetType(), defaultValue, value)
    
    End Sub
    
    ' 出力結果
    type = System.Int32, defaultValue = 0, value = 5
    type = System.Decimal, defaultValue = 0, value = 10
    

  •  指定の型とその値を渡すと、型の名前、規定値、渡した値を表示してくれるメソッドです。 誰得メソッドですが、まぁ勉強用なので良しとします。メソッド内にちらほら出てくる「T」という型がありますね。 これは、T という存在する型を指定しているの「ではなくて」、型パラメータという、仮の型です。 呼び出し元で、実際の型を指定するわけですが、ジェネリック内では、その型を「T」という仮の型で扱います。 これは、別に T ではなくても良くて、好きな文字に割り当てても OK です。ただ、慣習的に T が多く使われています。

  •  最後までこの記事を読んでいただき、ありがとうございました。

  • スポンサーリンク