2015-09-04 43 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

糟糕,名稱錯誤。然而,與接口相同的問題。我會解決它。 –

相關問題