VB.NET中的阴影与重载

时间:2010-03-25 11:35:25

标签: .net vb.net oop overloading shadows

当我们在C#中有new时,我个人认为只是作为一种解决方法来覆盖没有虚拟/可覆盖声明的属性,在VB.NET中我们有两个“概念”{{1} }和Shadows

在哪种情况下更喜欢彼此?

4 个答案:

答案 0 :(得分:18)

我确实通过使用Shadows vs Overloads编译相同的代码来确认基类中具有相同名称和签名的方法,并查看ildasm的输出。唯一的区别是Overloads案例指定hidebysig

这一点的重要性最好由Jon Skeet在this answer中解释。

但是,简单地说,如果基类具有重新定义的方法的重载,那么只有真正的区别:

  • Shadows会导致所有 过载是不可赎回的 派生类,其中为
  • Overloads仅替换 one 方法。

请注意,这只是一种语言结构,而不是由CLI强制执行(即C#和VB.NET强制执行此操作,但其他语言可能不执行此操作)。

一个简单的代码示例:

Module Module1

Sub Main()
    Dim a1 As C1 = New C2
    Dim a2 As New C2
    a1.M1()
    a2.M1()
    a1.M2()
    a2.M2()
    a1.M3()
    a2.M3()

    a1.M1(1)
    ' Overloads on M1() allows the M1(int) to be inherited/called.
    a2.M1(1)
    a1.M2(1)
    ' Shadows on M2() does not allow M2(int) to be called.
    'a2.M2(1)
    a1.M3(1)
    ' Shadows on M3() does not allow M3(int) to be called, even though it is Overridable.
    'a2.M3(1)

    If Debugger.IsAttached Then _
        Console.ReadLine()
End Sub

End Module

Class C1
Public Sub M1()
    Console.WriteLine("C1.M1")
End Sub
Public Sub M1(ByVal i As Integer)
    Console.WriteLine("C1.M1(int)")
End Sub
Public Sub M2()
    Console.WriteLine("C1.M2")
End Sub
Public Sub M2(ByVal i As Integer)
    Console.WriteLine("C1.M2(int)")
End Sub
Public Overridable Sub M3()
    Console.WriteLine("C1.M3")
End Sub
Public Overridable Sub M3(ByVal i As Integer)
    Console.WriteLine("C1.M3(int)")
End Sub
End Class

Class C2
Inherits C1
Public Overloads Sub M1()
    Console.WriteLine("C2.M1")
End Sub
Public Shadows Sub M2()
    Console.WriteLine("C2.M2")
End Sub
Public Shadows Sub M3()
    Console.WriteLine("C2.M3")
End Sub
' At compile time the different errors below show the variation.
' (Note these errors are the same irrespective of the ordering of the C2 methods.)
' Error: 'Public Overrides Sub M1(i As Integer)' cannot override 'Public Sub M1(i As Integer)' because it is not declared 'Overridable'.
'Public Overrides Sub M1(ByVal i As Integer)
'    Console.WriteLine("C2.M1(int)")
'End Sub
' Errors: sub 'M3' cannot be declared 'Overrides' because it does not override a sub in a base class.
'         sub 'M3' must be declared 'Shadows' because another member with this name is declared 'Shadows'.
'Public Overrides Sub M3(ByVal i As Integer)
'    Console.WriteLine("C2.M3(int)")
'End Sub
End Class

以上的输出:

C1.M1
C2.M1
C1.M2
C2.M2
C1.M3
C2.M3
C1.M1(int)
C1.M1(int)
C1.M2(int)
C1.M3(int)

输出显示直接调用Shadows时使用的C2调用,而不是通过C1间接调用时调用{/ 1}}。

答案 1 :(得分:13)

有三个密切相关的概念;覆盖,阴影和超载。

覆盖是指为虚拟方法创建新实现。

阴影是指为方法创建新的非虚拟实现。

重载是指添加具有相同名称但参数不同的方法。

C#和VB都提供了这三个概念。

答案 2 :(得分:0)

Shadows适用于您的基类为Function SomeMethod() As String并且您希望拥有Function SomeMethod() As Integer的情况。基本上,要更改返回类型。

Overloads适用于您的基类为Function SomeMethod() As String并且您想要添加Function SomeMethod(ByVal value As Integer) As String等参数的情况。

答案 3 :(得分:0)

Microsoft documentation指示:

  

阴影和重载Overloads也可用于在基类中隐藏现有成员或一组重载成员。以这种方式使用Overloads时,您声明的属性或方法的名称和参数列表与基类成员相同,并且不提供Shadows关键字。

因此,结果是相同的:子成员替换了基础成员。但是,您可能希望获得这种结果的原因通常分为两类:

  • 阴影-您希望确保子类的成员不会受到影响,以防随后向基类中添加了具有相同名称的新成员。在这种情况下,阴影成员通常尚不存在。 您只希望预见未来的问题
  • 重载-您希望用子类中的一个代替基类中成员的实现。在这种情况下,重载成员已经存在; 您希望更改行为

现在要记住,在定义阴影成员时,通常不存在阴影成员,因此默认情况下编译器会假设Shadows的原因变得显而易见。

与此Microsoft articleShadows关键字相关的部分也值得阅读。