vb.net specilized / overloaded generics

时间:2012-01-26 19:18:41

标签: vb.net generics overloading specialization

我倾向于不喜欢代码中的重复,所以当我遇到一个问题,其中唯一不同的类型我倾向于使用泛型。来自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 vs C ++感到沮丧的地方,AFAIK,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。

我的下一个解决方案是添加gtlt的通用版本:

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

嘿!不再编译错误,但是被调用的唯一例程是gtlt的通用版本。根据以前的说法我觉得有意义无法转换错误。我在遇到泛型例程的非泛型重载之前遇到过这个问题,我当时找不到解决方案,现在找不到解决方案了。

我有什么遗漏会使这种类型的重载成为可能吗?

编辑:一个完整​​的工作示例

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

1 个答案:

答案 0 :(得分:1)

来自Differences Between C++ Templates and C# Generics(与VB .NET相同):

  

C ++允许代码可能对所有类型参数无效   模板,然后检查用作类型的特定类型   参数。 C#要求类中的代码以这种方式编写   它将适用于满足约束的任何类型。对于   例如,在C ++中可以编写一个使用该函数的函数   算术运算符+和 - 在类型参数的对象上,其中   将在模板实例化时产生错误   使用不支持这些运算符的类型。 C#不允许这样做;   允许的唯一语言结构是可以推导出的结构   来自约束。

我无法使用.NET Generics解决您的问题。但是你可以通过使用lambdas和clos来避免重复逻辑,我认为这是在.NET中更自然的方式:

Public Sub Decision(ByVal a As String, ByVal b As Integer)
    Decision(b, Sub() gt(a), Sub() lt(a))
End Sub

Public Sub Decision(ByVal a As Integer, ByVal b As Integer)
    Decision(b, Sub() gt(a), Sub() lt(a))
End Sub

Private Sub decision(ByVal b As Integer, ByVal gt As Action, ByVal lt As Action)
    If b > 10 Then
        gt()
    Else
        lt()
    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