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)
精彩评论