3

If my class implements IEnumerable, I can use VBScript's For Each loop:

[ComVisible(true)]
[ProgId("Stackoverflow.MyIssues")]
[Guid("7D392CB1-9080-49D0-B9CE-05B214B2C448")]
public class MyIssue : IEnumerable
{
  readonly List<string> issues = new List<string>(new string[] { "foo", "bar" });

  public string this[int index]
  {
    get { return issues[index]; }
  }

  public IEnumerator GetEnumerator()
  {
    return issues.GetEnumerator();
  }
}


Dim o : Set o = CreateObject("Stackoverflow.MyIssues")

Dim i
For Each i In o
  WScript.Echo i
Next

If I change the interface to IEnumerable<string> (so C#'s foreach loop uses string instead of object):

public class MyIssue : IEnumerable<string>

and replace GetEnumerator with:

public IEnumerator<string> GetEnumerator()
{
  return issues.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
  return GetEnumerator();
}

The scritp will fail with an error:

Object Doesn't Support this Property or Method

My understanding is that the public GetEnumerator() is not exported, since it is a generic method, and the IEnumerable.GetEnumerator is not exported, since my instance must first be casted to IEnumerable but in VBScript one cannot cast objects.

Is this true? Is it possible to tell the compiler that IEnumerable.GetEnumerator should be exported as public IEnumerable GetEnumerator? (Or does this statement make no sense? etc.)

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
  • Scripting languages only support the default interface and don't provide a way to query another. [Unless you provide the help](http://stackoverflow.com/a/32405340/17034). There is no point in trying to expose the generic interface, it will never be used. – Hans Passant Oct 16 '15 at 12:26
  • a) Since the type library (http://pastebin.com/YiEwE3yT) did not change when changing the interface from `IEnumerable` to `IEnumerable`, I naively assumed it wouldn't matter. – Micha Wiedenmann Oct 19 '15 at 08:56
  • b) I thought, that essentially I "moved" `Mapper.ToEnum` to my class and renamed it to `IEnumerable.GetEnumerator()`. Now `IEnumerable.GetEnumerator()` is not callable as you explained. Therefore I asked: If I can make `GetEnumerator()` (or something newly created) callable from COM. I beg your pardon for being slow in grasping the picture and thank you for the explanations your provided so far! – Micha Wiedenmann Oct 19 '15 at 08:57

1 Answers1

2

Switch which interface is implemented explicitly, such as:

IEnumerator<string> IEnumerable<string>.GetEnumerator()
{
    // ...
}

public IEnumerator GetEnumerator()
{
    // ...
}

This is because IEnumerable.GetEnumerator has the DispId(-4) attribute, which is what VBScript uses through IDispatch.Invoke.

Generic methods and methods with generic types are not COM visible, so if you don't want to change your code, define an extra method for COM:

// Test if the .NET framework dispatches the method if you apply the following attribute
//[ComVisible(false)]
[DispId(-4)]
public IEnumerator NewEnum()
{
    return ((IEnumerable)this).GetEnumerator();
}
Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
acelent
  • 7,965
  • 21
  • 39