【发布时间】:2021-04-02 19:16:44
【问题描述】:
我的目标是进行一系列重载,根据参数的类型(仅在运行时知道)调用正确版本的方法。但是,在我要重载的方法是构造函数的情况下,我遇到了一个有趣的问题。
采用如下继承结构:
Public MustInherit Class A
Public Property Common As String
End Class
Public Class X
Inherits A
Public Property Unique1 As String
Public Property Unique2 As String
End Class
Public Class Y
Inherits A
Public Property Unique3 As String
Public Property Unique4 As String
End Class
基类A 被X 和Y 继承。
现在学习这门课,我将用它来展示问题:
Public Class Foo
Public Sub New(v As X)
Common = v.Common
Prop1 = v.Unique1
Prop2 = v.Unique2
Prop3 = "Some value"
Prop3 = String.Empty
End Sub
Public Sub New(v As Y)
Common = v.Common
Prop1 = "Some value"
Prop2 = String.Empty
Prop3 = v.Unique3
Prop4 = v.Unique4
End Sub
Public ReadOnly Property Common As String
Public ReadOnly Property Prop1 As String
Public ReadOnly Property Prop2 As String
Public ReadOnly Property Prop3 As String
Public ReadOnly Property Prop4 As String
Public Shared Sub Bar(v As X)
End Sub
Public Shared Sub Bar(v As Y)
End Sub
End Class
有一个带有重载的普通方法Bar,还有一个带有重载的构造函数New。第一个New与第一个Bar具有相同的签名,第二个New与第二个Bar具有相同的签名。
最后拿下这个测试代码:
Public Sub Test()
Dim Param As Object = New X
'This works fine
Foo.Bar(Param)
'This gives a compile error
Dim Thing As New Foo(Param)
End Sub
编译器对Bar的调用似乎没有问题,但是对于构造函数调用我得到以下编译错误:
重载解析失败,因为没有缩小转换就无法调用可访问的“新建”:
'Public Sub New(v As X)':参数匹配参数 'v' 从 'Object' 缩小到 'X'。
'Public Sub New(v As Y)':参数匹配参数 'v' 从 'Object' 缩小到 'Y'。
为什么构造函数调用会导致错误,而对 Bar 的调用不会。
另外,如果我将Param 声明更改为Dim Param As A = New X,那么它们都不会编译。
我觉得我应该理解这一点,但无论出于何种原因我都没有。有人可以告诉我为什么这不起作用,并可能提出解决方法吗?
【问题讨论】:
-
你有
Option Strict Off,设置On会更清晰。Dim Param As New X()对两者都有效。 -
@Jimi
Dim Param As New X会起作用,但这没有抓住重点。 “我的目标是进行一系列重载,根据参数的类型调用正确版本的方法(仅在运行时知道)。” -
然后实现一个接口而不是从一个抽象类继承。您还将获得泛型支持。拥有
Option Strict支持的意义在于,您会看到两个构造在编译时都失败了,所以您不需要问自己为什么一个失败?,因为两者实际上都失败了,这是只是暂时对你隐藏。 -
@Jimi 两对不都失败了。
Bar重载按预期工作。Dim Param As Object = New X导致Bar(v As X)被调用,Dim Param As Object = New Y导致Bar(v As Y)被调用。只有构造函数重载会产生任何错误。 -
对不起,
Option Strict Off的问题不仅在于它是Off(这直接暗示了所有这些),而是您在构建应用程序时考虑到了一种松散类型的模型,因此,太多的代码部分依赖于这个非特性(为简化 VB6 迁移而设计),试图忽略您正在使用的强类型框架。这会生成只是隐藏问题的代码。 -- 你正在尝试构建一个通用结构,但你不想谈论接口。 .Net 为此使用接口,而不是Object类型,并且继承仅限于单个类。
标签: vb.net overloading overload-resolution constructor-overloading