【问题标题】:Overload ignored inside generic function泛型函数内部忽略重载
【发布时间】:2021-08-01 15:56:23
【问题描述】:

当我运行以下类型检查代码时,它会产生结果:

True
False

这是为什么?

Module VBModule

    Class TypeKey(Of T)
        Public Sub New()

        End Sub
        Public Shared Operator =(k0 As TypeKey(Of T), k1 As TypeKey(Of T)) As Boolean
            Return True
        End Operator
        Public Shared Operator <>(k0 As TypeKey(Of T), k1 As TypeKey(Of T)) As Boolean
            Return False
        End Operator
        Public Shared Operator =(k0 As TypeKey(Of T), k1 As Object) As Boolean
            Return False
        End Operator
        Public Shared Operator <>(k0 As TypeKey(Of T), k1 As Object) As Boolean
            Return True
        End Operator
    End Class
    
    Public Function is_same_type(Of U, V)() As Boolean
        Return New TypeKey(Of U)() = New TypeKey(Of V)()
    End Function
 
    Sub Main()
        Console.WriteLine(New TypeKey(Of Integer)() = New TypeKey(Of Integer)())
        Console.WriteLine(is_same_type(Of Integer, Integer)())
    End Sub
  
End Module

在在线 VBNET IDE 上进行测试时,没有任何警告。

【问题讨论】:

  • 因为is_same_type(Of U, V)compiled once,而不是每个U, V。因此,它是根据编译时已知的U, V 编译的,即它们是object
  • 也许您已经习惯了 C++ 模板并且期望泛型的行为方式相同?如果您想检查类型是否相等,可以使用Type 进行检查。如果你想让is_same_type 工作,那么你不能使用Operator,因为它们不能是通用的(除了包含类),所以你不能得到一个适用于两个可能不同的类型参数在TypeKey;您需要编写一个非运算符函数。

标签: vb.net generics types


【解决方案1】:

没有警告

那是因为您有另一个带有 Object 参数的重载。所以,它又回到了那个。

那么,为什么它会以Object 参数开头呢?

这是因为Overload Resolution 是在编译时处理的,而不是在运行时处理的。在编译期间,编译器对您的类型V 一无所知。它无法知道它实际上与U 的类型相同在这个特定的实例中。因此,它总是使用Object 的重载。

您实际上可以通过两种方式确认这一点:

  1. 如果您将鼠标悬停在 = 运算符上,您可以看到正在使用的重载是 =(k0 As TypeKey(Of U), k1 As Object)

  2. 如果您删除(或注释掉)该重载,则会收到编译器错误并显示以下消息:

    重载解析失败,因为无法使用这些参数调用可访问的“=”:

    'Public Shared Operator =(k0 As VBModule.TypeKey(Of U), k1 As VBModule.TypeKey(Of U)) As Boolean': 'VBModule.TypeKey(Of V)' 类型的值不能转换为' VBModule.TypeKey(Of U)'。

    Try it online.

【讨论】:

  • 这是一个非常好的答案,但我没有看到解决方案,如果没有解决方案,请您这样说。
  • @Vye 解决方案到底是什么?您没有指定您要执行的操作的实际要求。您的问题只是“为什么我的代码会这样?”。为了提供解决方案,我们需要知道您的最终目标是什么。您只是想让Dim isEqual = New TypeKey(Of SomeType1)() = New TypeKey(Of SomeType2)() 更简洁吗?您是否真的希望 = 运算符始终为任意两个 TypeKey 对象返回 true,而不管泛型类型参数如何,还是 Return True 只是一个占位符?
  • 最好将此作为一个新问题发布。在您描述要求之前,我无法确定。如果原始问题没有彻底改变,我可能会编辑答案以解决它们。
  • @4168d6564 我正在寻找一种允许泛型函数正确使用重载运算符的解决方案;至于我试图将它用于is_same_type(Of U, V)() 应该以它的名称来解释。
  • @Vye 他们正在正确使用重载的运算符/方法。他们可能没有做你预期的事情,但他们正在做他们应该做的事情,如上所述。你确定这不是XY problem?根据您提供的当前信息,我认为我(或任何人)无法提出解决方案。我在之前的评论中问了你几个问题,但你似乎忽略了其中的大部分。根据您对这些问题的回答,我或许可以针对您尝试解决的实际问题提出解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多