0

文字列のテーブルから辞書を作成するルーチンがあります。正確なアプリケーションに応じて、これらの文字列は整数 ("123")、浮動小数点数 ("12.3")、または文字列 ("foo bar") を表す場合がありますが、明示的に記述した場合、有効な型はすべて文字列から直接キャストできます。たとえば、これは正常に動作します (VB.NET):

Class IntStrDict
    Sub Add()
        Dim k As String = "123"
        Dim v As String = "foo bar"
        Dim d As New Dictionary(Integer, String)
        d.Add(k, v)
    End Sub
End Class

しかし、このコードを一般的なものにしたいので、次のように書き直します。

Class PairDict(Of TKey, TValue)
    Sub Add(k As TKey, v As TValue)
        Dim k As String = "123"
        Dim v As String = "foo bar"
        Dim d As New Dictionary(TKey, TValue)
        d.Add(k, v)
    End Sub
End Class

しかし、.NET は String を TKey または TValue に直接キャストできることを認識していないため、これは機能しません。このようなクラスを宣言できる CastableFrom のようなインターフェイスはありますか?

Class PairDict(Of TKey As CastableFrom(Of String), TValue As CastableFrom(Of String))
4

2 に答える 2

0

インターフェイスタイプは、既存のインスタンスで動作するように設計されています。このように、のようなインターフェースは意味のある概念を表現します。を実装するIConvertableTo(Of Out TDest)タイプのオブジェクトがある場合、変換を実行できるものがあります。対照的に、インターフェイスを実装するオブジェクトができるまでインターフェイスを使用できないため、完全には機能しません。そのようなオブジェクトを作成する唯一の方法がインターフェースを介する場合、鶏が先か卵が先かという問題があります。FooIConvertable(Of Out Bar)IConvertableFrom(In TSrc)

いくつかの解決策があります。タイプIConverter(In TSrc, Out TDest)を持つことができ、変換を実行できる必要があるメソッドがそのタイプのインスタンスを受け入れることができます。あるいは、インスタンスを「空白」にしてから「入力」できるタイプがある場合は、の制約を使用できます{New,ILoadableFrom(In TSrc)}。これにより、次のようなことが可能になります。

Shared Function Convert(Of TSource, TDest As {New, ILoadableFrom(TSource)})(Src as TSource)
    Dim Result = New TDest()
    Result.LoadFrom(TSource)
    Return Result
End Function

このアプローチの最大の弱点は、宛先タイプにデフォルトのコンストラクターが含まれている必要があることです。検討する価値のあるもう1つのバリエーションは、契約の問題として、インターフェースを実装するすべてのタイプにICastableFrom(of T)静的メソッドが含まれている必要があることを要求することですFunction CastFrom(T param) As [itsOwnType]Function ICastableCast(Of TSrc, TDest)(src as TSrc) as TDest次に、 Reflectionを使用して静的メソッドを見つけTDest.CastFrom(param as TSrc) As TDestて呼び出す署名付きの静的メソッドを作成できます。Reflectionが(TSrc、TDest)ペアごとに1回だけ使用された場合、そのような方法はかなり高速になる可能性があります。

于 2013-01-12T18:24:07.460 に答える
0

この質問からそれを理解しました:CTypeDynamic(.NET 4.0+のみ)。これは機能しません:

Class PairDict(Of TKey, TValue)
    Sub Add(k As TKey, v As TValue)
        Dim k As String = "123"
        Dim v As String = "foo bar"
        Dim d As New Dictionary(TKey, TValue)
        d.Add(CType(k, TKey), CType(v, TValue))
    End Sub
End Class

...しかし、これは:

Class PairDict(Of TKey, TValue)
    Sub Add(k As TKey, v As TValue)
        Dim k As String = "123"
        Dim v As String = "foo bar"
        Dim d As New Dictionary(TKey, TValue)
        d.Add(CTypeDynamic(Of TKey)(k), CTypeDynamic(Of TValue)(v))
    End Sub
End Class

これは、誰かがこの機能で何をするかの便利な例です:

Public Class DictionaryGenerator(Of TKey, TValue)
    Public Function Generate(path As String, Optional excludeheader As Boolean = True) As Dictionary(Of TKey, TValue)
        Dim d As New Dictionary(Of TKey, TValue)

        Dim r As New Microsoft.VisualBasic.FileIO.TextFieldParser(path)
        r.TextFieldType = FileIO.FieldType.Delimited
        r.SetDelimiters(",")
        r.TrimWhiteSpace = True
        Dim csvline As String()
        If excludeheader Then r.ReadLine()
        While Not r.EndOfData
            csvline = r.ReadFields()
            d.Add(CTypeDynamic(Of TKey)(csvline(0)), CTypeDynamic(Of TValue)(csvline(1)))
        End While
        r.Close()

        Return d
    End Function
End Class
于 2013-01-11T00:29:11.190 に答える