【问题标题】:vb.net specilized/overloaded genericsvb.net 特化/重载泛型
【发布时间】:2012-01-26 19:18:41
【问题描述】:

我倾向于讨厌代码中的重复,所以当我遇到唯一不同的是类型的问题时,我倾向于使用泛型。来自 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 类型无法转换为字符串或整数的错误

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

【问题讨论】:

  • 问题不在于你对decision 的声明,而是调用方法或类——请告诉我们。您的情况不需要泛型,您最初显示的重载很好。
  • 添加了一个演示问题的工作示例,附加代码将出现无法转换错误,将#if False Then 更改为#If True Then 将始终调用通用版本。
  • 是的,我明白,但这也不是问题所在。你能做一些真实的例子吗?
  • 不幸的是没有。我不喜欢发布公司代码,即使我知道它不会造成任何伤害,我只是不想冒险。我想我不确定还需要什么,因为上面的代码与我在其他地方遇到的问题相同,也许如果你让我知道你在寻找什么,我可以提供更多信息。从那以后,我想出了另一种解决问题的方法,但是由于我两次遇到这个问题,我现在对提供的示例更感兴趣,所以我知道将来如何解决这个问题。我有上面代码的 C++ 版本,可以正常工作。
  • 嗯......这种情况永远不需要。如果你有另一个修复,那很好。但是没有实际的方法和调用方法我就忍不住了。

标签: vb.net generics overloading specialization


【解决方案1】:

来自Differences Between C++ Templates and C# Generics(同样适用于 VB .NET):

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

我无法用 .NET 泛型解决您的问题。但是您可以通过使用 lambda 和闭包来避免重复逻辑,我也认为在 .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 

【讨论】:

  • 嗯,我使用泛型的原因是为了减少重复代码的数量,尤其是逻辑分支代码。听起来这将是我能做的最好的事情。什么版本的 .NET 引入了 lambda?
  • Lambdas 是在 .NET 3.5 发布的 VB 9/VS2008 中引入的。但是,可以将目标框架设置为 .NET 2.0(如此处所述:stackoverflow.com/a/1162235/953288)。
  • 不错!我从来没有想过为此目的使用 lambdas。对于它的价值,可能与 C++ 在运行时发生的情况接近的替代方法是依赖于泛型和分支,具体取决于类型参数(通过反射使用GetType(T))。但是,您失去了强类型保护以及性能(据说反射是贪婪的)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-26
  • 2012-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-09
相关资源
最近更新 更多