2015-09-04 51 views
4

为什么使用For Each重复ArrayList而不是Hashtable为什么用`For Each`迭代Hashtable不能在VBScript中工作?

Dim i 

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

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

迭代HashTable

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

+1

我猜Hashtable对象尚未建立与枚举支持。你可以用字典吗?您可以遍历一个Dictionary。 – eurotrash

回答

6

脚本语言有技术限制,他们只能使用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成员。只有入口,关键和价值,它们是无用的。对于Keys和Values集合也是如此:

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

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


这可以解决。需要的是可以使用默认接口获取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; 
     } 
    } 
} 

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

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

我对你的第一句话感到困惑,因为'DictionaryEntry'似乎是'ComVisible(true)'(根据:https://msdn.microsoft.com/de-de/library/System.Collections.DictionaryEntry%28v= vs.110%29.aspx和http://referencesource.microsoft.com/#mscorlib/system/collections/dictionaryentry.cs)。 –

+0

糟糕,名称错误。然而,与接口相同的问题。我会解决它。 –

相关问题