Shadows vs Overloads in VB.NET

后端 未结 4 1757
面向向阳花
面向向阳花 2020-12-02 23:20

When we have new in C#, that personally I see only as a workaround to override a property that does not have a virtual/overridable declaration, in VB.NET we hav

4条回答
  •  广开言路
    2020-12-03 00:04

    I have actually confirmed by compiling the same code with Shadows vs Overloads for a method with an identical name and signature in the base class and looking at the output from ildasm for both. The only difference is the Overloads case specifies hidebysig.

    The significance of this is best explained by Jon Skeet in this answer.

    But simply it means there is only a real difference if the base class has overloads of the method being redefined:

    • Shadows will cause all of those overloads to be uncallable through the derived class, where as
    • Overloads only replaces the one method.

    Note that this is only a language construct and not enforced by the CLI (i.e. C# and VB.NET enforce this but other languages may not).

    A simple code example:

    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
    

    The output of the above:

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

    The output shows the Shadows calls are used when C2 is called directly and not when called indirectly through C1.

提交回复
热议问题