2013年6月10日月曜日

VB.NET でデフォルト値を指定できる Dictionary クラスを作る

VB.NET のサンプル。VB2008 で確認。VB のバージョンが古いと動作しないかもしれない。
Dictionary クラスを継承して、デフォルトのプロパティーを上書きして実現。

※ VB.NET ではデフォルトのプロパティーを使うと、オブジェクト名(引数) のように、オブジェクト名にドットを付けず、直接カッコと引数を付けた時に呼ばれるサブルーチンを作成できる。

.NET の Dictionary コンテナは、Hashtable と異なり、値を代入していないキーを参照すると、例外KeyNotFoundException を投げる。

下記の Dic2 クラスは、コンストラクタでデフォルト値を指定(または DefaultValue メンバにデフォルト値を代入)できる。 使うときは、ソースの末尾などに下の基本版または完全版のコードを追加してから
Dim d As New Dic2(of integer,string)("デフォルト値")
などとして d の宣言と初期化を行う。d は Dictionary 型のオブジェクトとして使用でき、値を代入していないキーを参照すると、例外KeyNotFoundException を投げずにデフォルト値を返す。

基本版


' ---------------- このクラスをコードの末尾に挿入して定義してください
' Dic2: デフォルト値を持つ Dictionary コンテナ
' USAGE: dim h as new Dic2(of キーの型, 値の型)(デフォルト値)
' 
' 使用例:
' Dim h As New Dic2(Of Integer, String)("デフォルト")
' h(0) = "文字列"
Public Class Dic2(Of TK1, TV)
  Inherits Dictionary(Of TK1, TV)
  Public DefaultValue As TV = Nothing
  ' --- 基底クラスのコンストラクタ
  Public Sub New(ByRef a1 As Dictionary(Of TK1, TV))
    MyBase.New(a1)
  End Sub
  ' --- 追加のコンストラクタ
  Public Sub New()
  End Sub
  Public Sub New(ByVal def As TV)
    DefaultValue = def
  End Sub
  ' --- 引数1個の Item() メソッド
  Default Shadows Property item(ByVal a1 As TK1) As TV
    Get
      If (Not MyBase.ContainsKey(a1) And DefaultValue IsNot Nothing) Then Return DefaultValue
      Return MyBase.Item(a1)
    End Get
    Set(ByVal value As TV)
      MyBase.Item(a1) = value
    End Set
  End Property
End Class

コンストラクタを追加した完全版

' ---------------- このクラスをコードの末尾に挿入して定義してください
' Dic2: デフォルト値を持つ Dictionary コンテナ
' USAGE: dim h as new Dic2(of キーの型, 値の型)(デフォルト値)
' 
' 使用例:
' Dim h As New Dic2(Of Integer, String)("デフォルト")
' h(0) = "文字列"
<Serializable()> Public Class Dic2(Of TK1, TV)
    Inherits Dictionary(Of TK1, TV)
    Public DefaultValue As TV = Nothing
    ' --- 基底クラスのコンストラクタ
    Public Sub New(ByRef a1 As Dictionary(Of TK1, TV))
        MyBase.New(a1)
    End Sub
    Public Sub New(ByRef a1 As IEqualityComparer(Of TK1))
        MyBase.New(a1)
    End Sub
    'Public Sub New(ByRef a1 As Int32)
    '   MyBase.New(a1)
    'End Sub
    Public Sub New(ByRef a1 As IDictionary(Of TK1, TV), ByRef a2 As IEqualityComparer(Of TK1))
        MyBase.New(a1, a2)
    End Sub
    Public Sub New(ByRef a1 As Int32, ByRef a2 As IEqualityComparer(Of TK1))
        MyBase.New(a1, a2)
    End Sub
    '---- シリアライズ
    Private Sub New(ByVal info As System.Runtime.Serialization.SerializationInfo, _
                    ByVal context As System.Runtime.Serialization.StreamingContext)
        MyBase.New(info, context)
        DefaultValue = info.GetValue("DEFAULT", GetType(TV)) ' 追加したメンバ
    End Sub
    Public Overrides Sub GetObjectData(ByVal info As System.Runtime.Serialization.SerializationInfo, _
                             ByVal context As System.Runtime.Serialization.StreamingContext)
        MyBase.GetObjectData(info, context)
        info.AddValue("DEFAULT", DefaultValue) ' 追加したメンバ
    End Sub
    ' --- 追加のコンストラクタ
    Public Sub New()
    End Sub
    Public Sub New(ByVal def As TV)
        DefaultValue = def
    End Sub
    ' --- 引数1個の Item() メソッド
    Default Shadows Property item(ByVal a1 As TK1) As TV
        Get
            If (Not MyBase.ContainsKey(a1) And DefaultValue IsNot Nothing) Then Return DefaultValue
            Return MyBase.Item(a1)
        End Get
        Set(ByVal value As TV)
            MyBase.Item(a1) = value
        End Set
    End Property
End Class

0 件のコメント:

コメントを投稿