VB.NET 中的阴影与重载

发布于 2024-08-26 16:53:43 字数 150 浏览 10 评论 0原文

当我们在 C# 中使用 new 时,我个人认为这只是重写没有虚拟/可重写声明的属性的一种解决方法,在 VB.NET 中我们有两个“概念”Shadows重载

在哪种情况下更喜欢其中一种?

When we have new in C#, that personally I see only as a workaround to override a property that does not have a virtual/overridable declaration, in VB.NET we have two "concepts" Shadows and Overloads.

In which case prefer one to another?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

猥︴琐丶欲为 2024-09-02 16:53:43

实际上,我已经通过使用 ShadowsOverloads 编译相同的代码来确认基类中具有相同名称和签名的方法,并查看 ildasm 的输出两者都适用。唯一的区别是 Overloads 情况指定了 hidebysig。

Jon Skeet 在这个答案中最好地解释了这一点的重要性。

但简单来说,这意味着只有当基类重载了正在重新定义的方法时,才会有真正的区别:

  • 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)

输出显示直接调用 C2 时使用 Shadows 调用,而不是通过 C1 间接调用时使用 Shadows 调用代码>.

I have actually confirmed by compiling the same code with Shadows vs Overloads for a method with an identical name and signature in the base class and looking at the output from ildasm for both. The only difference is the Overloads case specifies hidebysig.

The significance of this is best explained by Jon Skeet in this answer.

But simply it means there is only a real difference if the base class has overloads of the method being redefined:

  • Shadows will cause all of those
    overloads to be uncallable through
    the derived class, where as
  • Overloads only replaces the one method.

Note that this is only a language construct and not enforced by the CLI (i.e. C# and VB.NET enforce this but other languages may not).

A simple code example:

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

The output of the above:

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

The output shows the Shadows calls are used when C2 is called directly and not when called indirectly through C1.

全部不再 2024-09-02 16:53:43

存在三个密切相关的概念;覆盖、遮蔽和超载。

重写是指为虚拟方法创建新的实现。

影子是指为方法创建新的非虚拟实现。

重载是指添加具有相同名称但参数不同的方法。

所有三个概念在 C# 和 VB 中都可用。

There are three closely related concepts; overriding, shadowing and overloading.

Overriding is when you make a new implementation for a virtual method.

Shadowing is when you make a new non-virtual implementation for a method.

Overloading is when you add a method with the same name but different parameters.

All three concepts are available both in C# and VB.

半岛未凉 2024-09-02 16:53:43

Microsoft 文档指出:

阴影和过载。重载还可用于隐藏基类中的现有成员或重载成员集。当您以这种方式使用Overloads时,您声明的属性或方法与基类成员具有相同的名称和相同的参数列表,并且不提供Shadows关键字。

因此,结果是相同的:子成员替换基本成员。然而,您希望实现这种结果的原因通常分为两类:

  • 阴影 - 您希望确保您的子班级成员不会受到同名新成员的影响随后添加到基类中。在这种情况下,影子成员通常还不存在; 您只想预见未来的问题
  • 重载 - 您希望用子类中的成员替换基类中成员的实现。在这种情况下,重载成员已经存在; 您希望改变行为

现在考虑到在定义影子成员时影子成员通常不存在,编译器默认情况下假设影子的原因就变得显而易见了。

引用此 微软文章也值得一读。

The Microsoft documentation indicates:

Shadowing and Overloading. Overloads can also be used to shadow an existing member, or set of overloaded members, in a base class. When you use Overloads in this way, you declare the property or method with the same name and the same parameter list as the base class member, and you do not supply the Shadows keyword.

Hence, the result is the same: the child member replaces the base member. However the reasons why you may wish to achieve such result typically fall under two categories:

  • Shadows - You wish to make sure that member of your child class will not be affected in case a new member with the same name is subsequently added to the base class. In that case, the shadowed member typically does not exist yet; you only wish to anticipate problems for the future.
  • Overloads - You wish to substitute the implementation of a member in the base class by that one of your child class. In that case, the overloaded member already exists; you wish to alter a behaviour.

Having now in mind that a shadowed member typically does not exist at the time the shadowing member is defined, the reasons why by default the compiler will assume Shadows become obvious.

The parts referring to the Shadows keyword of this Microsoft article are also worth reading.

你的背包 2024-09-02 16:53:43

Shadows 适用于基类为 Function SomeMethod() As String 并且您希望使用 Function SomeMethod() As Integer 的情况。基本上,改变返回类型。

Overloads 适用于基类为 Function SomeMethod() As String 并且您想要添加参数,例如 Function SomeMethod(ByVal value As Integer) As字符串

Shadows is for cases where your base class is Function SomeMethod() As String and you want to have Function SomeMethod() As Integer. Basically, to change the return type.

Overloads is for case where your base class is Function SomeMethod() As String and you want to add a parameter such as Function SomeMethod(ByVal value As Integer) As String.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文