Quando abbiamo una new
in C #, che personalmente vedo solo come soluzione alternativa per sostituire una proprietà che non ha una dichiarazione virtuale / sovrascrivibile, in VB.NET abbiamo due “concetti” Shadows
e Overloads
.
In tal caso preferisci l’uno all’altro?
Ci sono tre concetti strettamente correlati; sovrascrittura, ombreggiamento e sovraccarico.
L’override avviene quando si effettua una nuova implementazione per un metodo virtuale.
Lo shadowing è quando si realizza una nuova implementazione non virtuale per un metodo.
Il sovraccarico si ha quando si aggiunge un metodo con lo stesso nome ma diversi parametri.
Tutti e tre i concetti sono disponibili sia in C # che in VB.
In realtà ho confermato compilando lo stesso codice con Shadows
vs Overloads
per un metodo con un nome e una firma identici nella class base e guardando l’output di ildasm
per entrambi. L’unica differenza è che il caso Overloads
specifica hidebysig
.
Il significato di questo è spiegato meglio da Jon Skeet in questa risposta .
Ma semplicemente significa che c’è solo una vera differenza se la class base ha sovraccarichi del metodo ridefinito:
Shadows
causano l’impossibilità di tutti questi sovraccarichi attraverso la class derivata, dove come Overloads
sostituisce solo l’ unico metodo. Si noti che questo è solo un costrutto linguistico e non applicato dalla CLI (cioè C # e VB.NET impongono questo, ma altre lingue potrebbero non esserlo).
Un semplice esempio di codice:
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
L’output di quanto sopra:
C1.M1 C2.M1 C1.M2 C2.M2 C1.M3 C2.M3 C1.M1(int) C1.M1(int) C1.M2(int) C1.M3(int)
L’output mostra che le chiamate Shadows
vengono utilizzate quando C2
viene chiamato direttamente e non quando viene chiamato indirettamente tramite C1
.
Shadows
è per i casi in cui la class base è Function SomeMethod() As String
e si desidera avere Function SomeMethod() As Integer
. Fondamentalmente, per cambiare il tipo di ritorno.
Overloads
è per il caso in cui la class base è Function SomeMethod() As String
e si desidera aggiungere un parametro come Function SomeMethod(ByVal value As Integer) As String
.