24

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 have two "concepts" Shadows and Overloads.

In which case prefer one to another?

Mark Hurd
  • 10,665
  • 10
  • 68
  • 101
serhio
  • 28,010
  • 62
  • 221
  • 374

4 Answers4

24

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.

Community
  • 1
  • 1
Mark Hurd
  • 10,665
  • 10
  • 68
  • 101
  • 1
    This should definitely be the accepted answer as it explains a key distinction between the two concepts, from which we can logically deduct all the other differences described in other answers . – Ama Feb 05 '20 at 22:19
18

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.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • 2
    The question is not about overriding, this is OK. Now **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 argument list as the base class member, and you do not supply the Shadows keyword. I see *new* (C#) = *Shadows* (VB.NET), what is the C# equivalent to overloads? – serhio Mar 25 '10 at 11:53
  • @serhio: I just mentioned overriding for completeness because it's a closely related concept. As the Overloads keyword in VB can also be used for shadowing, there is no exact equivalent in C#. In C# there is no keyword for overloading, you just declare a method with the same name and different signature to overload it. – Guffa Mar 25 '10 at 12:53
  • 1
    so, your definitions is not complete, so these 2 concepts remains unclear for me. `Shadows` creates a "new" function, and `Overloads` is (can be) used for the same scope. so what the difference. – serhio Mar 26 '10 at 11:34
  • @serhio: Well, the definitions of the concepts is pretty complete (while there is of course a lot more that you can explain about them). The concepts doesn't map 1-to-1 to the VB keywords, so while you sometimes can use the `Overloads` keyword to to shadowing it's still shadowing that you do. The concepts remain the same even when the VB keywords overlap. – Guffa Mar 26 '10 at 13:08
  • 1
    I agree. However in practice I use keywords not concepts, and if I have the same(non-virtual) method with the same parameters in the child class, VS warns me to use the "Overloads" keyword, but not the "Shadows" one, like it should result from the concept that you described. – serhio Mar 26 '10 at 18:12
  • @serhio: Well, actually you use both the keyword and the concept. :) Although the `Overloads` keyword seems to be useable for most situations where you can use the `Shadows` keyword, I would recommend that you use the keyword that corresponds to the actual concept that you are using, that makes the code easier to read. – Guffa Mar 26 '10 at 19:08
  • @serhio: The warnings that you get from the compiler usually suggests what works in most situations, not neccesarily what fits best. – Guffa Mar 26 '10 at 19:19
  • @Guffa: "fits best"... for me, both Shadows and Overloads fits good. Finally, if the result is the same, that is no sense to have both. Oh... what why I prefer C#: no strange ambiguity, no necessity to "be compatible" with the archaic syntax... Thanks, Guffa. Let's close this topic and go on. – serhio Mar 26 '10 at 23:48
  • Under the context of the OP - that is, the definition a member in a child class - I believe the definition of overloading is misleading as you could indeed overload and "add a method with the same name and parameters". See my proposed answer. – Ama Sep 17 '19 at 15:10
1

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.

Ama
  • 1,373
  • 10
  • 24
0

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.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
  • 2
    **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 argument list as the base class member, and you do not supply the Shadows keyword. – serhio Mar 25 '10 at 12:21