I tend to loath repetition in code, so when I come across a problem where the only different is types I tend to use generics. Coming from a C++ background I find vb.net’s version to be rather frustrating, I know C++ has template specialization and I guess vb.net does not
so what I have is a set of routines that do the exact same code regardless of type being passed.
something like this
Public Sub decision(Of T)(ByVal a As T, ByVal b As Integer)
If b > 10 then
gt(a)
Else
lt(a)
End If
End Sub
I am only ever passing two types to routine, Strings and Integers and what those routines do with string differs from what it does with integers.
Public Sub gt(ByVal a As String)
Public Sub gt(ByVal a As Integer)
Public Sub lt(ByVal a As String)
Public Sub lt(ByVal a As Integer)
This is where I get frustrated with vb.net vs C++, AFAIK, C++ would check the types at compile time and only against what types are sent to decision. However, in vb.net I get an error that type T cannot be converted to String or Integer
Error 3 Overload resolution failed because no accessible 'gt' can be called with these arguments:
'Public Sub gt(a As String)': Value of type 'T' cannot be converted to 'String'.
'Public Sub gt(a As Integer)': Value of type 'T' cannot be converted to 'Integer'.
I tried constraints Public Sub decision(Of T As {String, Integer})(ByVal a As T, ByVal b As Integer) but constraints need to be Inheritable classes so neither String, nor Integer can be used.
My Next Solution was to add a generic versions of gt and lt:
Public Sub lt(Of T)(ByVal a As T)
Debug.Fail("Not Implemented")
End Sub
Public Sub lt(Of T)(ByVal a As T)
Debug.Fail("Not Implemented")
End Sub
And hey! no more compile errors however the only routine that gets called is the generic version of gt and lt. Which I guess makes sense in light of the previous cannot convert errors. I’ve encountered this issue before where there are non-generic overloads of a generic routine, I could not find a solution then, and I cannot find a solution now.
Is there something I am missing that would make this type of overloading possible?
Edit: a complete working example
Module Module1
Sub Main()
decision(1, 5)
decision(1, 10)
decision("hello world", 5)
decision("hello world", 10)
End Sub
Public Sub decision(Of T)(ByVal a As T, ByVal b As Integer)
If b > 10 Then
gt(a)
Else
lt(a)
End If
End Sub
Public Sub gt(ByVal a As String)
Debug.WriteLine(" gt string: " + a)
End Sub
Public Sub gt(ByVal a As Integer)
Debug.WriteLine(" gt integer: " + a.ToString)
End Sub
Public Sub lt(ByVal a As String)
Debug.WriteLine(" lt string: " + a)
End Sub
Public Sub lt(ByVal a As Integer)
Debug.WriteLine(" lt integer: " + a.ToString)
End Sub
#If False Then
Public Sub gt(Of T)(ByVal a As T)
Debug.Fail("Not implemented")
End Sub
Public Sub lt(Of T)(ByVal a As T)
Debug.Fail("Not implemented")
End Sub
#End If
End Module
From Differences Between C++ Templates and C# Generics (the same holds for VB .NET):
I’m not able to solve your problem with .NET Generics. But you can avoid repeating the logic by using lambdas and closures, which I also think is a more natural way to do it in .NET: