KeyedList 实现






4.83/5 (23投票s)
2003年12月25日
2分钟阅读

166633

869
键值列表 (KeyedList) 实现一个有序的键值列表。
引言
KeyedList
是一个有序的键值列表。相比之下
Hashtable
是一个无序的键值列表;SortedList
是一个排序后的键值列表;ArrayList
是一个有序列表。
但在 System.Collections
命名空间中,没有实现一个有序键值列表的类。
难道没人做过这个吗?
出于某种原因,微软决定将 KeyedList
作为 System.Web.UI
命名空间的一部分来实现。请参考 这份初步的 MSDN 文档,它是 Longhorn 的一部分。为什么要在 System.Web.UI
中实现这个?我需要的是一个平台无关的 KeyedList
!在 Google 上搜索了一下,我发现 Mono 项目中有一个代码实现,这里 和 这里。
实现
下面的代码采用了 Todd Berman 编写的实现,移除了 IStateManager
接口,并将实现放置在 System.Collections
命名空间中,而不是 System.Web.UI
。这并非什么高深的技术,但由于我在 CP 上没有找到任何 KeyedList
文章,所以我觉得这里是一个放置这个有价值类的合适地方。KeyedList
也继承了 Longhorn MSDN 中指定的接口,而不是 Mono 实现中使用的接口。总而言之,我认为我花在 Google 上搜索有序 Hashtable 的时间比从 Mono 链接中提取代码并略微修改它们的时间还要多!
using System; using System.Collections; namespace System.Collections { public interface IOrderedDictionary { void Insert(Int32 index, Object key, Object value); void RemoveAt(Int32 index); } [Serializable] public class KeyedList : ICollection, IDictionary, IEnumerable, IOrderedDictionary { private Hashtable objectTable = new Hashtable (); private ArrayList objectList = new ArrayList (); public void Add (object key, object value) { objectTable.Add (key, value); objectList.Add (new DictionaryEntry (key, value)); } public void Clear () { objectTable.Clear (); objectList.Clear (); } public bool Contains (object key) { return objectTable.Contains (key); } public void CopyTo (Array array, int idx) { objectTable.CopyTo (array, idx); } public void Insert (int idx, object key, object value) { if (idx > Count) throw new ArgumentOutOfRangeException ("index"); objectTable.Add (key, value); objectList.Insert (idx, new DictionaryEntry (key, value)); } public void Remove (object key) { objectTable.Remove (key); objectList.RemoveAt (IndexOf (key)); } public void RemoveAt (int idx) { if (idx >= Count) throw new ArgumentOutOfRangeException ("index"); objectTable.Remove ( ((DictionaryEntry)objectList[idx]).Key ); objectList.RemoveAt (idx); } IDictionaryEnumerator IDictionary.GetEnumerator () { return new KeyedListEnumerator (objectList); } IEnumerator IEnumerable.GetEnumerator () { return new KeyedListEnumerator (objectList); } public int Count { get { return objectList.Count; } } public bool IsFixedSize { get { return false; } } public bool IsReadOnly { get { return false; } } public bool IsSynchronized { get { return false; } } public object this[int idx] { get { return ((DictionaryEntry) objectList[idx]).Value; } set { if (idx < 0 || idx >= Count) throw new ArgumentOutOfRangeException ("index"); object key = ((DictionaryEntry) objectList[idx]).Key; objectList[idx] = new DictionaryEntry (key, value); objectTable[key] = value; } } public object this[object key] { get { return objectTable[key]; } set { if (objectTable.Contains (key)) { objectTable[key] = value; objectTable[IndexOf (key)] = new DictionaryEntry (key, value); return; } Add (key, value); } } public ICollection Keys { get { ArrayList retList = new ArrayList (); for (int i = 0; i < objectList.Count; i++) { retList.Add ( ((DictionaryEntry)objectList[i]).Key ); } return retList; } } public ICollection Values { get { ArrayList retList = new ArrayList (); for (int i = 0; i < objectList.Count; i++) { retList.Add ( ((DictionaryEntry)objectList[i]).Value ); } return retList; } } public object SyncRoot { get { return this; } } private int IndexOf (object key) { for (int i = 0; i < objectList.Count; i++) { if (((DictionaryEntry) objectList[i]).Key.Equals (key)) { return i; } } return -1; } } public class KeyedListEnumerator : IDictionaryEnumerator { private int index = -1; private ArrayList objs; internal KeyedListEnumerator (ArrayList list) { objs = list; } public bool MoveNext () { index++; if (index >= objs.Count) return false; return true; } public void Reset () { index = -1; } public object Current { get { if (index < 0 || index >= objs.Count) throw new InvalidOperationException (); return objs[index]; } } public DictionaryEntry Entry { get { return (DictionaryEntry) Current; } } public object Key { get { return Entry.Key; } } public object Value { get { return Entry.Value; } } } }
使用键值列表 (KeyedList)
使用 KeyedList
就像使用 Hashtable
一样,除了当你枚举列表时,条目会按照它们被添加到列表的顺序排列。相信我,我确实需要这个功能!
using System; using System.Collections; namespace KeyedListTest { class ConsoleApp { [STAThread] static void Main(string[] args) { KeyedList k=new KeyedList(); k.Add("One", 1); k.Add("Two", 2); k.Add("Three", 3); k.Add("Four", 4); k.Add("Five", 5); k.Add("Six", 6); k.Add("Seven", 7); k.Add("Eight", 8); k.Add("Nine", 9); k.Add("Ten", 10); foreach(DictionaryEntry entry in k) { Console.WriteLine(entry.Key+": "+entry.Value.ToString()); } } } }
结论
就这样!一点 Google 搜索,一点对现有源代码的调整,瞧!,一个解决我特定问题的方案,也许有一天也能解决您的问题。