开发者

Generic Class with Specific Instantiation

I have a generic class:

Public Class MyClass(Of K,V)

  Private _Dictionary As Dictionary(Of K,V)

  Sub New
   _Dictionary = New Dictionary(Of K,V)
  End Sub

End Class

I would like to overload New for the specific case where K is String:

Sub New(sc As StringComparer)
  _Dictionary = New Dictionary(Of String,V)(sc)
End Sub

This results 开发者_如何学Cin the error:

Dictionary(Of String, V) cannot be converted to Dictionary(Of K, V)

It doesn't look like I'm going about this the right way but hopefully I've managed to explain what I'm trying to do.


You need to do something like this:

Public Class [MyClass](Of K,V)

    Private _Dictionary As Dictionary(Of K,V)

    Public Sub New()
        _Dictionary = New Dictionary(Of K, V)
    End Sub

    Public Sub New(comparer As IEqualityComparer(Of K))
        _Dictionary = New Dictionary(Of K, V)(comparer)
    End Sub

End Class

'This class now optional as per comment
Public Class MyStringClass(Of V)
    Inherits [MyClass](Of String, V)

    Public Sub New(sc As StringComparer)
        MyBase.New(sc)
    End Sub

End Class


Generic types are created on the fly when your application runs. When you refer to GenericClass(Of String, Integer), it loads a customised version of the class into memory. When you later refer to GenericClass(Of String, Long), it loads another, separate, customized class into memory. You can't access any members, including constructors, until the class is loaded. You'll always have to refer to GenericClass(Of String, V) before you can call one of it's contructors.

There are a few options available to you. None of them are any more readable than the original code. The main problem is you can only refer to the class by specifying both the K and V types.


Method 1: Static method

Use a shared/static Create method to create the object.

Public Class GenericClass(Of K, V)

    Private _Dictionary As Dictionary(Of K, V)

    Sub New()
        _Dictionary = New Dictionary(Of K, V)
    End Sub

    Public Shared Function Create(sc As StringComparer) As GenericClass(Of String, V)
        Dim NewObject As New GenericClass(Of String, V)
        ' TODO: Initialise object.
        Return NewObject
    End Function
End Class

You create the object with:

Dim sc As StringComparer = New StringComparer()
Dim MyObject As GenericClass(Of String, ValueType) = GenericClass(Of String, ValueType).Create(sc)

Method 2: Inherited class

Create an inherited class that enforces the K type as a String.

Public Class NotSoGenericClass(Of V)
    Inherits GenericClass(Of String, V)

    Public Sub New(sc As StringComparer)
        MyBase.New()
        ' TODO: Initialise object.
    End Sub
End Class

You create the object with:

Dim sc As StringComparer = New StringComparer()
Dim MyObject As New NotSoGenericClass(Of ValueType)(sc)

or

Dim sc As StringComparer = New StringComparer()
Dim MyObject As GenericClass(Of String, ValueType) = New NotSoGenericClass(Of ValueType)(sc)

Method 3: Static class

You can create a static class (Private Sub New prevents it being instantised) or a module containing the Create method. This one has the same name as the GenericClass, but without the type specifiers.

Public Class GenericClass

    Private Sub New()
    End Sub

    Public Shared Function Create(Of V)(sc As StringComparer) As GenericClass(Of String, V)
        Dim NewObject As New GenericClass(Of String, V)
        ' TODO: Initialise object.
        Return NewObject
    End Function
End Class

You create the object with:

Dim sc As StringComparer = New StringComparer()
Dim MyObject As GenericClass(Of String, ValueType) = GenericClass.Create(Of ValueType)(sc)

Method 4: Throw an exception

You can create a contructor that throws an exception if it's used incorrectly. The problem with this is the IDE doesn't reccognise this restriction and will let the constructor be called on invalid K types.

Sub New(sc As StringComparer)
    If GetType(K) IsNot GetType(String) Then Throw New InvalidCastException("Type K must be String for this constructor.")
    _Dictionary = New Dictionary(Of K, V)
End Sub

You create the object with:

Dim sc As StringComparer = New StringComparer()
Dim MyObject As New GenericClass(Of String, ValueType)(sc)

But this throws an exception:

Dim sc As StringComparer = New StringComparer()
Dim MyObject As New GenericClass(Of Object, ValueType)(sc)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜