哪种方法重载可以从 VBScript 访问?

Which method overload will be accessible from VBScript?

System.Collections.ArrayListComVisible(true)。它包含 IndexOf 的三个重载(参见 here):

public virtual int IndexOf(Object value)
public virtual int IndexOf(Object value, int startIndex)
public virtual int IndexOf(Object value, int startIndex, int count)

从 VBScript 中,只能访问第二个重载:

Dim oList
Set oList = CreateObject("System.Collections.ArrayList")

'oList.IndexOf "foo"        'Error: Invalid procedure call or argument: 'IndexOf'
 oList.IndexOf "foo", 0
'oList.IndexOf "foo", 0, 1  'Error: Wrong number of arguments or property assignment was not valid: 'IndexOf'

'Overloading a method in com visible dll' 中,Hans Passant 解释说 程序集中存在重载方法,但无法从脚本中获取它们 dispid 因此称呼他们。这似乎意味着一种方法可能会成功。

重载有编号的别名:

>> Set al = CreateObject("System.Collections.ArrayList")
>> al.Add "poo"
>> al.Add "foo"
>> WScript.Echo al.IndexOf("poo", 0)
>>
0
>> WScript.Echo al.IndexOf("poo", 1)
>>
-1
>> WScript.Echo al.IndexOf_1("foo")
>>
Error Number:       438
Error Description:  Object doesn't support this property or method
>> WScript.Echo al.IndexOf_2("foo")
>>
Error Number:       5
Error Description:  Invalid procedure call or argument
>> WScript.Echo al.IndexOf_3("foo")
>>
1
>>

我通过反复试验来弄清楚;可能会有更科学的方法的文档或内省工具。

简答:全部。


我们来分析一下@hans-passant写了什么;

Answer to Overloading a method in com visible dll
COM does not have support for member overloads, each name must be unique. An inevitable side-effect of IDispatch::GetIDsOfNames(). The function that the script interpreter uses to translate "Write" as used in the scripting code to a dispid. The method still exists, there's just no way to get GetIDsOfNames() to return its dispid. The type library exporter solves this problem by renaming the overloaded method, it will be Write_2().

分为两部分

  1. 解释 IDispatch::GetIDsOfNames()
  2. 的行为
  3. 类型库导出器如何解决唯一性问题。

并不是说它们不可用,相反,它们已被重命名以避免 IDispatch::GetIDsOfNames() 在将 DISPID 分配给方法名称时具有的唯一性约束。

所以所有三个重载都可用,只是使用以下格式重命名

oList.IndexOf
oList.IndexOf_2
oList.IndexOf_3

Note: There is no IndexOf_1 because the first overload always takes the original method name and subsequent overloads start from _2 onwards.

根据类型库导出器重命名重载的方式,重载将取决于哪一个采用哪组参数,解决这个问题的唯一方法是反复试验。

快速尝试测试

Dim oList
Set oList = CreateObject("System.Collections.ArrayList")

oList.Add "bar"
oList.Add "foo"

WScript.Echo oList.IndexOf("foo", 0)
WScript.Echo oList.IndexOf_2("foo", 0, 1)
WScript.Echo oList.IndexOf_3("foo")

输出:

1
-1
1

为什么这两个语句会因不同的错误而失败?

如果我们回到你原来的例子

Dim oList
Set oList = CreateObject("System.Collections.ArrayList")

'oList.IndexOf "foo"        'Error: Invalid procedure call or argument: 'IndexOf'
 oList.IndexOf "foo", 0
'oList.IndexOf "foo", 0, 1  'Error: Wrong number of arguments or property assignment was not valid: 'IndexOf'

由于 VBScript 评估方法签名的方式不同,语句一和语句三失败并出现不同的错误。上面示例中的正确签名接受两个参数,因此第一个语句;

oList.IndexOf "foo"

将失败,因为唯一匹配的签名有两个参数而不是一个参数,因此会出现错误;

Invalid procedure call or argument: 'IndexOf'

第三条语句

oList.IndexOf "foo", 0, 1

比预期的签名多了一个参数,因此不是没有找到匹配,而是找到一个匹配但报告;

Wrong number of arguments or property assignment was not valid: 'IndexOf'

因为参数的数量超出了方法签名的预期数量 IndexOf(arg, arg)


有用的链接