2010-03-25 26 views
20

當我們在C#中有new時,我個人認爲它只是一種替代沒有虛擬/可重寫聲明的屬性的解決方法,在VB.NET中我們有兩個「概念」ShadowsOverloadsVB.NET中的陰影與過載

在哪種情況下比較喜歡一個?

回答

13

有三個密切相關的概念;覆蓋,陰影和超載。

覆蓋是當您爲虛擬方法制作新實現時。

影子是當你爲一個方法做一個新的非虛擬實現。

重載是當您添加一個具有相同名稱但參數不同的方法時。

這三個概念都可以在C#和VB中使用。

+1

問題不在於重寫,這是可以的。現在,**重載**也可用於**在基類中映射現有成員或一組重載成員。當以這種方式使用重載時,您聲明與基類成員具有相同名稱和相同參數列表的屬性或方法,並且不提供Shadows關鍵字。我看* new *(C#)= * Shadows *(VB.NET),什麼是C#等同於重載? – serhio 2010-03-25 11:53:09

+0

@serhio:我剛剛提到覆蓋的完整性,因爲它是一個密切相關的概念。由於VB中的Overloads關鍵字也可以用於陰影,所以在C#中沒有完全相同的東西。在C#中沒有用於重載的關鍵字,你只需聲明一個具有相同名稱和不同簽名的方法來重載它。 – Guffa 2010-03-25 12:53:24

+1

所以,你的定義不完整,所以這2個概念對我來說還不清楚。 'Shadows'創建一個「new」函數,'Overloads'被(可以)用於相同的範圍。所以有什麼區別。 – serhio 2010-03-26 11:34:39

0

Shadows適用於您的基本類別爲Function SomeMethod() As String且您想擁有Function SomeMethod() As Integer的情況。基本上,要改變返回類型。

Overloads適用於您的基類爲Function SomeMethod() As String的情況,並且您想添加諸如Function SomeMethod(ByVal value As Integer) As String之類的參數。

+2

**重載**也可用於**映射基類中的現有成員或一組重載成員。當以這種方式使用重載時,您聲明與基類成員具有相同名稱和相同參數列表的屬性或方法,並且不提供Shadows關鍵字。 – serhio 2010-03-25 12:21:00

16

其實我已經通過編譯與Shadows VS Overloads相同的代碼用於與在基類相同的名稱和簽名的方法和從ildasm兩個查看輸出確認。唯一的區別是Overloads案例指定hidebysig

Jon Skeet在this answer中最好地解釋了這一點的重要性。

但僅僅意味着只有當基類有該方法的重載被重新定義一個真正的區別:

  • Shadows將導致所有這些 重載是uncallable通過 派生類,其中作爲
  • Overloads只取代一個方法。

請注意,這只是一種語言結構,並不由CLI實施(即C#和VB.NET強制執行此操作,但其他語言可能不執行此操作)。

一個簡單的代碼例如:

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 

上述的輸出:

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

輸出示出了當通過C1間接調用時C2直接和不使用所謂的的Shadows呼叫。