Search code examples
c#.netvb.netnew-operatorshadows

Difference between Shadows (VB.NET) and New (C#)


Simple question from a simple-minded: What are the differences between the Shadows keyword in VB.NET and the New keyword in C#? (regarding method signatures of course).


Solution

  • They are not identical.

    The Shadowing concept does not exist in C #

    Consider a vb.net base class with some overloads:

    Public Class BaseClass
        Public Function SomeMethod() As String
            Return String.Empty
        End Function
        Public Function SomeMethod(SomeParam As String) As String
            Return "Base from String"
        End Function
    
        Public Function SomeMethod(SomeParam As Integer) As String
            Return "Base from Integer"
        End Function
        Public Function SomeMethod(SomeParamB As Boolean) As String
            Return "Base from Boolean"
        End Function
    End Class
    

    And this derived class:

    Public Class DerivedClass
        Inherits BaseClass
    
        Public Shadows Function SomeMethod(SomeParam As String) As String
            Return "Derived from String"
        End Function
    End Class
    

    Now consider the implementation:

    Dim DerivedInstance = New DerivedClass()
    

    DerivedInstance have just one version of SomeMethod, and all other base versions have been shadowed.

    if you compile and reference the assembly in a C# project you can see what happens:

    DerivedInstance shadows method

    To perform hiding in VB.Net, you still have to use the overloads (or overrides if base method is marked as overridable) keyword:

    Public Class DerivedClass
        Inherits BaseClass
    
        Public Overloads Function SomeMethod(SomeParam As String) As String
            Return "Derived from String"
        End Function
    End Class
    

    And this is what happens after compiling:

    DerivedInstance hide method

    So, in VB.Net, if you use overloads keyword, on a signature that matches one on base class, you're hiding that base version of method, just like you would in c #:

    public class DerivedClass : BaseClass
    {
        public new string SomeMethod(string someParam)
        {
            return "Derived from String";
        }
    }
    

    Edit: This is the IL code:

    From C#:

    .method public hidebysig specialname rtspecialname instance void .ctor () cil managed 
    {
        IL_0000: ldarg.0
        IL_0001: call instance void Shadowing_CS.BaseClass::.ctor()
        IL_0006: ret
    }
    
    .method public hidebysig instance string SomeMethod (
            string s
        ) cil managed 
    {
        IL_0000: ldstr "Derived from string"
        IL_0005: ret
    }
    

    From VB:

    .method public specialname rtspecialname instance void .ctor () cil managed 
    {
        IL_0000: ldarg.0
        IL_0001: call instance void Shadowing_VB.BaseClass::.ctor()
        IL_0006: ret
    }
    
    .method public instance string SomeMethod (
            string s
        ) cil managed 
    {
        IL_0000: ldstr "Derived from string"
        IL_0005: ret
    }
    

    So.... they are not identical.