当我们new
在 C# 中时,我个人认为这只是一种解决方法来覆盖没有虚拟/可覆盖声明的属性,在 VB.NET 中我们有两个“概念”Shadows
和Overloads
.
在哪种情况下更喜欢一个?
当我们new
在 C# 中时,我个人认为这只是一种解决方法来覆盖没有虚拟/可覆盖声明的属性,在 VB.NET 中我们有两个“概念”Shadows
和Overloads
.
在哪种情况下更喜欢一个?
实际上,我已经通过使用Shadows
vsOverloads
为基类中具有相同名称和签名的方法编译相同的代码并查看ildasm
两者的输出来确认。唯一的区别是Overloads
大小写指定hidebysig
。
Jon Skeet 在这个答案中最好地解释了这一点的重要性。
但简单地说,这意味着只有基类具有被重新定义的方法的重载时才会有真正的区别:
Shadows
将导致所有这些重载都无法通过派生类调用,其中 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)
输出显示Shadows
调用在直接调用时使用,C2
而不是在通过 间接调用时使用C1
。
存在三个密切相关的概念;覆盖,阴影和重载。
覆盖是当您为虚拟方法创建新实现时。
阴影是当您为方法创建新的非虚拟实现时。
重载是当您添加具有相同名称但不同参数的方法时。
这三个概念在 C# 和 VB 中都可用。
Microsoft 文档指出:
阴影和重载。
Overloads
也可用于隐藏基类中的现有成员或重载成员集。以这种方式使用Overloads
时,您声明的属性或方法与基类成员具有相同的名称和相同的参数列表,并且您不提供Shadows
关键字。
因此,结果是相同的:子成员替换了基础成员。但是,您可能希望获得此类结果的原因通常分为两类:
现在考虑到在定义遮蔽成员时通常不存在遮蔽成员,编译器默认假设的原因Shadows
变得显而易见。
提到这篇微软文章Shadows
的关键字的部分也值得一读。
Shadows
适用于您的基类是Function SomeMethod() As String
并且您希望拥有Function SomeMethod() As Integer
. 基本上,改变返回类型。
Overloads
适用于您的基类是Function SomeMethod() As String
并且您想要添加参数的情况,例如Function SomeMethod(ByVal value As Integer) As String
.