vb.net 专用/重载泛型
我倾向于讨厌代码中的重复,因此当我遇到唯一不同的是类型的问题时,我倾向于使用泛型。来自 C++ 背景,我发现 vb.net 的版本相当令人沮丧,我知道 C++ 有模板专业化,但我猜 vb.net 没有 所以我拥有的是一组例程,无论传递的类型如何,它们都会执行完全相同的代码。
像这样的事情
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)
Public Sub gt(ByVal a As Integer)
Public Sub lt(ByVal a As String)
Public Sub lt(ByVal a As Integer)
这就是我对 vb.net 与 C++ 感到沮丧的地方,据我所知,C++ 会在编译时检查类型,并且仅根据发送的类型进行决策。但是,在 vb.net 中,我收到一个错误,类型 T 无法转换为 String 或 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'.
我尝试了约束 Public Sub Decision(Of T As {String, Integer})(ByVal a As T, ByVal b As Integer)
但约束必须是可继承类,因此不能使用 String 或 Integer。
我的下一个解决方案是添加 gt
和 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
嘿!不再有编译错误,但是唯一被调用的例程是 gt
和 lt
的通用版本。鉴于之前的无法转换错误,我认为这是有道理的。我以前遇到过这个问题,其中存在通用例程的非通用重载,当时我找不到解决方案,现在也找不到解决方案。
我是否缺少某些东西可以使这种类型的重载成为可能?
编辑:一个完整的工作示例
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
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
来自C++ 模板和 C# 泛型之间的差异(这同样适用于 VB .网):
我无法使用 .NET 泛型解决您的问题。但是您可以通过使用 lambda 和闭包来避免重复逻辑,我也认为这是在 .NET 中执行此操作的更自然的方式:
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: