Shadows vs Overloads in VB.NET

后端 未结 4 1740
面向向阳花
面向向阳花 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-02 23:53

    Shadows is for cases where your base class is Function SomeMethod() As String and you want to have Function SomeMethod() As Integer. Basically, to change the return type.

    Overloads is for case where your base class is Function SomeMethod() As String and you want to add a parameter such as Function SomeMethod(ByVal value As Integer) As String.

    0 讨论(0)
  • 2020-12-02 23:59

    The Microsoft documentation indicates:

    Shadowing and Overloading. Overloads can also be used to shadow an existing member, or set of overloaded members, in a base class. When you use Overloads in this way, you declare the property or method with the same name and the same parameter list as the base class member, and you do not supply the Shadows keyword.

    Hence, the result is the same: the child member replaces the base member. However the reasons why you may wish to achieve such result typically fall under two categories:

    • Shadows - You wish to make sure that member of your child class will not be affected in case a new member with the same name is subsequently added to the base class. In that case, the shadowed member typically does not exist yet; you only wish to anticipate problems for the future.
    • Overloads - You wish to substitute the implementation of a member in the base class by that one of your child class. In that case, the overloaded member already exists; you wish to alter a behaviour.

    Having now in mind that a shadowed member typically does not exist at the time the shadowing member is defined, the reasons why by default the compiler will assume Shadows become obvious.

    The parts referring to the Shadows keyword of this Microsoft article are also worth reading.

    0 讨论(0)
  • 2020-12-03 00:01

    There are three closely related concepts; overriding, shadowing and overloading.

    Overriding is when you make a new implementation for a virtual method.

    Shadowing is when you make a new non-virtual implementation for a method.

    Overloading is when you add a method with the same name but different parameters.

    All three concepts are available both in C# and VB.

    0 讨论(0)
  • 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.

    0 讨论(0)
提交回复
热议问题