重载决策 (Visual Basic)
当 Visual Basic 编译器遇到对多个重载版本中定义的过程的调用时,编译器必须确定要调用的重载。 它通过执行以下步骤来实现这一目的:
可访问性。 它消除了具有访问级别的任何重载,使调用代码无法调用它。
参数数目。 它消除了定义的参数数量与调用中提供的参数数量不同的任何重载。
参数数据类型。 编译器使实例方法优先于扩展方法。 如果找到了只需要扩大转换即可匹配过程调用的任何实例方法,则将删除所有扩展方法,且编译器仅继续处理实例方法候选项。 如果未找到此类实例方法,则它将继续执行实例和扩展方法。
在此步骤中,它将消除调用参数的数据类型无法转换为重载中定义的参数类型的任何重载。
收缩转换。 它消除了任何需要从调用参数类型到已定义参数类型的收缩转换的重载。 无论类型检查开关(Option Strict 语句)为
On
或Off
,都是如此。最少扩大。 编译器将其余重载视为成对。 对于每个对,它将比较已定义参数的数据类型。 如果其中一个重载中的类型全部扩大到另一个重载中的相应类型,则编译器将消除后者。 即,它会保留需要最少扩大量的重载。
单个候选项。 它继续考虑成对重载,直到只剩一个重载,并解析对该重载的调用。 如果编译器无法将重载减少到单个候选项,则会生成错误。
下图显示了确定要调用的一组重载版本的过程。
下面的示例演示了此重载决策过程。
Overloads Sub z(ByVal x As Byte, ByVal y As Double)
End Sub
Overloads Sub z(ByVal x As Short, ByVal y As Single)
End Sub
Overloads Sub z(ByVal x As Integer, ByVal y As Single)
End Sub
Dim r, s As Short
Call z(r, s)
Dim p As Byte, q As Short
' The following statement causes an overload resolution error.
Call z(p, q)
在第一次调用中,编译器将消除第一个重载,因为第一个参数的类型 (Short
) 会缩小到相应参数的类型 (Byte
)。 然后,它将消除第三个重载,因为第二个重载中的每个参数类型(Short
和 Single
)都将扩大到第三个重载中的相应类型(Integer
和 Single
)。 第二个重载需要更少的扩大,因此编译器将其用于调用。
在第二次调用中,编译器无法根据收缩消除任何重载。 它消除第三个重载的原因与第一次调用相同,因为它可以通过减少扩大参数类型来调用第二个重载。 但编译器无法在第一个和第二个重载之间解析。 每个重载都有一个定义的参数类型,该类型会扩大到其他重载中的相应类型(Byte
到 Short
,Single
到 Double
)。 因此,编译器将生成重载决策错误。
重载的 Optional 参数和 ParamArray 参数
如果过程的两个重载具有相同的签名,则除了最后一个参数在一个重载中声明为 Optional,在另一个重载中声明为 ParamArray 外,编译器将解析对该过程的调用,如下所示:
如果调用提供最后一个参数为 | 编译器解析对声明最后一个参数为以下形式的重载的调用 |
---|---|
没有值(省略参数) | Optional |
单个值 | Optional |
采用逗号分隔列表形式的两个或更多值 | ParamArray |
任意长度的数组(含空数组) | ParamArray |