【问题标题】:Why does iterating a Hashtable with `For Each` not work in VBScript?为什么在 VBScript 中使用“For Each”迭代 Hashtable 不起作用?
【发布时间】:2015-11-30 10:30:23
【问题描述】:

为什么可以使用For Each 迭代ArrayList 而不能使用Hashtable

Dim i

For Each i In CreateObject("System.Collections.ArrayList") ' no error
Next

For Each i In CreateObject("System.Collections.Hashtable") ' error
Next

迭代HashTable 得到

对象不支持此属性或方法。

【问题讨论】:

  • 我猜 HashTable 对象还没有构建支持枚举。你能用字典代替吗?您可以遍历字典。

标签: .net vbscript com


【解决方案1】:

脚本语言有一个技术限制,它们只能使用 coclass 的默认接口。他们根本没有接口的概念,也没有通过 IUnknown::QueryInterface() 获取另一个接口的后门。就像您可以在 C# 中通过转换为所需的接口类型一样。 ArrayList 的迭代器如下所示:

private sealed class ArrayListEnumeratorSimple : IEnumerator, ICloneable {
   // etc...
}

IEnumerator 是默认界面,您可以在 VBScript 中使用它。但是,Hashtable 的枚举器看起来像这样:

private class HashtableEnumerator : IDictionaryEnumerator, IEnumerable, ICloneable {
   // etc..
}

IDictionaryEnumerator 是默认值,而不是 IEnumerable。因此 VBScript 找不到所需的 Current 和 MoveNext 成员。只有Entry、Key和Value,它们是无用的。 Keys and Values 集合也差不多:

public class KeysCollection : ICollection, IEnumerable {
   // etc..
}

同样的问题,CopyTo、Count、IsSynchronized 和 SyncRoot 都没用。通过将 [ComDefaultInterface] 属性应用于这些类,Microsoft 可以很容易地解决此问题。但他们没有。


这可以解决。需要的是可以 QI 默认接口以获得 IEnumerable 接口的代码。你可以帮助一个小的 C# 类库项目:

using System;
using System.Collections;
using System.Runtime.InteropServices;

namespace VBScript
{
    [ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface IMapper {
        IEnumerable ToEnum(object itf);
    }

    [ComVisible(true), ProgId("VBScript.Mapper")]
    public class Mapper : IMapper {
        public IEnumerable ToEnum(object itf) {
            return (IEnumerable)itf;
        }
    }
}

使用 32 位和 64 位版本的 Regasm 构建和注册程序集。现在你可以让这个脚本工作了:

Set table = CreateObject("System.Collections.Hashtable")
table.Add 1, "one"
table.Add 2, "two"
Set mapper = CreateObject("VBScript.Mapper")
For Each key in mapper.ToEnum(table.Keys)
   WScript.Echo key & ": " & table(key)
Next

输出:

Microsoft (R) Windows Script Host Version 5.812
Copyright (C) Microsoft Corporation. All rights reserved.

1: one
2: two

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-10
  • 2015-06-19
  • 1970-01-01
  • 2010-10-17
  • 1970-01-01
  • 2021-08-03
相关资源
最近更新 更多