5

System.Collections.ArrayList is ComVisible(true). It contains three overloads of IndexOf (see 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)

From VBScript, only the second overload can be accessed:

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'

In 'Overloading a method in com visible dll' Hans Passant explains that overload methods exist in the assembly, but from script one cannot get their dispid and therefore call them. This seems to imply that one method might make it through though.

  • Can I determine from the ArrayList source (or elsewhere), which method will be accessible? What are the rules, that govern this selection process?
  • Why are the error messages different for case one and three?
Community
  • 1
  • 1
Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
  • 2
    As is stated [here(MSDN)](https://msdn.microsoft.com/en-us/library/ms182197.aspx), _When overloaded methods are exposed to COM clients, only the first method overload retains its name_ . I don't know why this is not the case,unless the code provided in your link is not accurate... – Pikoh May 03 '16 at 10:26
  • Like @Pikoh say's only the first overload retains the name *(also Hans points this out - "The type library exporter solves this problem by renaming the overloaded method, it will be `Write_2()`.")* why you not trying `oList.IndexOf_2 "foo", 0` and `oList.IndexOf_3 "foo", 0, 1`? – user692942 May 03 '16 at 11:00
  • 1
    In fact all methods are exposed. For example, you can access the one parameter override with :`oList.IndexOf_3 "foo"` or the 3 parameters as `oList.IndexOf_2 "foo", 0, 1` – Pikoh May 03 '16 at 11:03
  • @Pikoh It's just working out in which order the overloads are exposed when the Type Exporter renames them `IndexOf()`, `IndexOf_2()` and `IndexOf_3()` which isn't hard. Fairly confident [Hans already covers this](http://stackoverflow.com/a/25650296/692942) in the other question. – user692942 May 03 '16 at 11:09
  • @ShadowWizard Good find, also confirms order is based off original order they are defined in the assembly. – user692942 May 03 '16 at 12:15
  • Thanks @Lankymart that wasn't easy to find, needed bunch of key words. – Shadow The GPT Wizard May 03 '16 at 12:17
  • @ShadowWizard Yep, didn't come up on my radar. Still think Hans explanation of the behaviour is a bit more concise. – user692942 May 03 '16 at 12:19
  • 1
    @ShadowWizard Another dup [Overloads in COM interop (CCW) - IDispatch names include suffix (_2, _3, etc)](http://stackoverflow.com/q/1277740/692942) – user692942 May 03 '16 at 12:32
  • @Lankymart yeah, not sure which to close now... maybe better leave it like that. (i.e. close this one as dupe of what I found, leaving the other one as-is) – Shadow The GPT Wizard May 03 '16 at 12:38
  • @micha You've been very quiet, did any of the suggestions help? – user692942 May 04 '16 at 08:47
  • 1
    @Lankymart Thank you, I have thinking about it. It turns out, that my question was a bad question, because it based on a wrong assumption. Nevertheless the answers have been helpful and seem useful in general. Since this is a chatty comment to update you, I will delete it in 24 h to clean up the comments for other viewers. Thank you for being so supportive. – Micha Wiedenmann May 04 '16 at 09:24
  • @MichaWiedenmann I wouldn't worry about that and you're welcome. Thanks for the update. – user692942 May 04 '16 at 09:25

2 Answers2

3

The overloads have numbered aliases:

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

I use trial and error to figure it out; there may be docs or introspection tools for a more scientific approach.

Ekkehard.Horner
  • 38,498
  • 2
  • 45
  • 96
3

Short answer: All of them.


Let's analyse what @hans-passant has written;

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().

It's in two parts

  1. Explaining the behaviour of IDispatch::GetIDsOfNames()
  2. How the Type Library Exporter solves uniqueness issue.

It doesn't say they are not available, on the contrary they have been renamed to avoid the uniqueness constraint that IDispatch::GetIDsOfNames() has when assigning DISPID to the method name.

So all three overloads are available just renamed using the following format

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.

Depending on how the Type Library Exporter renames the overloads will depend which one takes which set of arguments, the only way to work this out is trial and error.

Quick attempt at a test

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

Output:

1
-1
1

Why do the two statements fail with different errors?

If we go back to your original example

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'

Statement one and three fail with different errors due to how VBScript evaluates the method signatures. The correct signature in the above example accepts two arguments so the first statement;

oList.IndexOf "foo"

will fail because the only matching signature has two arguments not one hence the error;

Invalid procedure call or argument: 'IndexOf'

The third statement

oList.IndexOf "foo", 0, 1

contains one more argument then the expected signature so instead of not finding a match it finds one but reports;

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

as the number of arguments exceeds what is expected by the method signature IndexOf(arg, arg).


Useful Links

Community
  • 1
  • 1
user692942
  • 16,398
  • 7
  • 76
  • 175