当我们在C#中有new
时,我个人认为只是作为一种解决方法来覆盖没有虚拟/可覆盖声明的属性,在VB.NET中我们有两个“概念”{{1} }和Shadows
。
在哪种情况下更喜欢彼此?
答案 0 :(得分:18)
我确实通过使用Shadows
vs Overloads
编译相同的代码来确认基类中具有相同名称和签名的方法,并查看ildasm
的输出。唯一的区别是Overloads
案例指定hidebysig
。
这一点的重要性最好由Jon Skeet在this answer中解释。
但是,简单地说,如果基类具有重新定义的方法的重载,那么只有真正的区别:
Shadows
会导致所有
过载是不可赎回的
派生类,其中为Overloads
仅替换 one 方法。请注意,这只是一种语言结构,而不是由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)
输出显示直接调用Shadows
时使用的C2
调用,而不是通过C1
间接调用时调用{/ 1}}。
答案 1 :(得分:13)
有三个密切相关的概念;覆盖,阴影和超载。
覆盖是指为虚拟方法创建新实现。
阴影是指为方法创建新的非虚拟实现。
重载是指添加具有相同名称但参数不同的方法。
C#和VB都提供了这三个概念。
答案 2 :(得分:0)
Shadows
适用于您的基类为Function SomeMethod() As String
并且您希望拥有Function SomeMethod() As Integer
的情况。基本上,要更改返回类型。
Overloads
适用于您的基类为Function SomeMethod() As String
并且您想要添加Function SomeMethod(ByVal value As Integer) As String
等参数的情况。
答案 3 :(得分:0)
阴影和重载。
Overloads
也可用于在基类中隐藏现有成员或一组重载成员。以这种方式使用Overloads
时,您声明的属性或方法的名称和参数列表与基类成员相同,并且不提供Shadows
关键字。
因此,结果是相同的:子成员替换了基础成员。但是,您可能希望获得这种结果的原因通常分为两类:
现在要记住,在定义阴影成员时,通常不存在阴影成员,因此默认情况下编译器会假设Shadows
的原因变得显而易见。
与此Microsoft article的Shadows
关键字相关的部分也值得阅读。