3

A For...Each loop in VBx uses the IEnumVARIANT member of an object which supports automation with a method of DISPID_NEWENUM = -4 to iterate over its contents.

However the VBx SAFEARRAY is not an automation object deriving from IDispatch (it is not a COM object at all) and does not have an IEnumVARIANT returning method. How then does For...Each work on an array under the hood? Is there a standard method to create an IEnumVARIANT from a SAFEARRAY? Or is this interpreter special-casing?

Greedo
  • 4,967
  • 2
  • 30
  • 78
  • For Each works on an a collection (DISPID_NEWENUM) or an array. There's no "special case" beyond that, but these are not special case. – Simon Mourier Sep 29 '22 at 11:57
  • I wouldn't think there's any reason For...Each has to operate identically on objects and arrays. For... Each could be overloaded at the compiler level. You can, after all, emulate the behavior using xBound() and For... Next – Jim Mack Sep 29 '22 at 13:39
  • 1
    `For Each A In B` cannot be (always) overloaded at compiler level because if `B` is `Variant` it can be both an object or an array at different times so the codegen has to expect both cases. VB6 uses wrapper functions in the runtime to access `IEnumVARIANT` enumerator for objects or creates short-lived its own custom enumerator for arrays (probably not `IEnumVARIANT` based). – wqw Sep 30 '22 at 06:32
  • @wqw thanks that's an important point on Variant inputs, hinting at the existence of some kind of dynamic runtime function. But if you haven't found a way to call it then I doubt there's much chance! I don't suppose any of those wrapper functions are exposed, right now I'm invoking `DISPID_NEWENUM` manually with `DispCallFunc` which is messy and a bit slow. – Greedo Sep 30 '22 at 07:21
  • I no longer use For Each. I wrote an Iterator class (IterItems) that completely replaces the functionality of For Each, which can iterate forwards/backwards/over specified range, change iteration direction mid sequence as manytimes as I like, provides Item/Index/Key (with relative addressing) and can take as its input arrays, collections,dictionaries,queues,stacks,strings and even single values. By creating multiple iterItem objects I can also iterate multiple entities in Parallel. It may not be as fast as For Each but its a lot more flexible and programmer friendly. I used twinBasic. – freeflow Sep 30 '22 at 08:56

0 Answers0