1 namespace System.Collections.Specialized
\r
4 public class ListDictionary : IDictionary, ICollection, IEnumerable
\r
7 private int modCount;
\r
8 private ListEntry root;
\r
9 private IComparer comparer;
\r
12 public ListDictionary()
\r
20 public ListDictionary(IComparer comparer) : this()
\r
22 this.comparer = comparer;
\r
25 private bool AreEqual(object obj1, object obj2)
\r
27 if (comparer != null) {
\r
28 if (comparer.Compare(obj1, obj2) == 0) {
\r
32 if (obj1.Equals(obj2)) {
\r
40 private ListEntry FindEntry(object key)
\r
43 throw new ArgumentNullException("Attempted lookup for a null key.");
\r
49 ListEntry entry = root;
\r
51 while (entry != null) {
\r
52 if (AreEqual(key, entry.key)) {
\r
63 private void AddImpl(object key, object value)
\r
66 throw new ArgumentNullException("Attempted add with a null key.");
\r
70 root = new ListEntry();
\r
74 ListEntry entry = root;
\r
76 while (entry != null) {
\r
77 if (AreEqual(key, entry.key)) {
\r
78 throw new ArgumentException("Duplicate key in add.");
\r
81 if (entry.next == null) {
\r
88 entry.next = new ListEntry();
\r
89 entry.next.key = key;
\r
90 entry.next.value = value;
\r
97 // IEnumerable Interface
\r
98 IEnumerator IEnumerable.GetEnumerator()
\r
100 return new ListEntryEnumerator(this);
\r
103 // ICollection Interface
\r
110 public bool IsSynchronized {
\r
116 public object SyncRoot {
\r
122 public void CopyTo(Array array, int index)
\r
125 throw new ArgumentNullException(
\r
127 "Array cannot be null.");
\r
130 throw new ArgumentOutOfRangeException("index", "index is less than 0");
\r
133 foreach ( DictionaryEntry entry in this )
\r
134 array.SetValue( entry, i++ );
\r
137 // IDictionary Interface
\r
138 public bool IsFixedSize
\r
145 public bool IsReadOnly
\r
153 public object this[object key]
\r
156 ListEntry entry = FindEntry(key);
\r
157 return entry == null ? entry : entry.value;
\r
161 ListEntry entry = FindEntry(key);
\r
163 entry.value = value;
\r
165 AddImpl(key, value);
\r
169 public ICollection Keys
\r
172 return new ListEntryCollection(this, true);
\r
176 public ICollection Values
\r
179 return new ListEntryCollection(this, false);
\r
183 public void Add(object key, object value)
\r
185 AddImpl(key, value);
\r
188 public void Clear()
\r
195 public bool Contains(object key)
\r
197 return FindEntry(key) != null ? true : false;
\r
200 public IDictionaryEnumerator GetEnumerator()
\r
202 return new ListEntryEnumerator(this);
\r
205 public void Remove(object key)
\r
208 throw new ArgumentNullException(
\r
210 "Key cannot be null.");
\r
213 ListEntry entry = root;
\r
215 for (ListEntry prev = null; entry != null; prev = entry, entry = entry.next) {
\r
216 if (AreEqual(key, entry.key)) {
\r
217 if (prev != null) {
\r
218 prev.next = entry.next;
\r
223 entry.value = null;
\r
231 private class ListEntry
\r
233 public object key = null;
\r
234 public object value = null;
\r
235 public ListEntry next = null;
\r
239 private class ListEntryEnumerator : IEnumerator, IDictionaryEnumerator
\r
241 private ListDictionary dict;
\r
242 private bool isAtStart;
\r
243 private ListEntry current;
\r
244 private int version;
\r
246 public ListEntryEnumerator(ListDictionary dict)
\r
249 version = dict.modCount;
\r
253 private void FailFast()
\r
255 if (version != dict.modCount) {
\r
256 throw new InvalidOperationException(
\r
257 "The ListDictionary's contents changed after this enumerator was instantiated.");
\r
261 public bool MoveNext()
\r
266 current = dict.root;
\r
269 current = current.next;
\r
272 return current != null ? true : false;
\r
275 public void Reset()
\r
283 public object Current
\r
288 if (isAtStart || current == null) {
\r
289 throw new InvalidOperationException(
\r
290 "Enumerator is positioned before the collection's first element or after the last element.");
\r
293 return new DictionaryEntry(current.key, current.value);
\r
297 // IDictionaryEnumerator
\r
298 public DictionaryEntry Entry
\r
302 return (DictionaryEntry) Current;
\r
311 if (isAtStart || current == null) {
\r
312 throw new InvalidOperationException(
\r
313 "Enumerator is positioned before the collection's first element or after the last element.");
\r
316 return current.key;
\r
320 public object Value
\r
325 if (isAtStart || current == null) {
\r
326 throw new InvalidOperationException(
\r
327 "Enumerator is positioned before the collection's first element or after the last element.");
\r
330 return current.value;
\r
335 private class ListEntryCollection : ICollection
\r
337 private ListDictionary dict;
\r
338 private bool isKeyList;
\r
340 public ListEntryCollection(ListDictionary dict, bool isKeyList)
\r
343 this.isKeyList = isKeyList;
\r
346 // ICollection Interface
\r
353 public bool IsSynchronized
\r
360 public object SyncRoot
\r
363 return dict.SyncRoot;
\r
367 public void CopyTo(Array array, int index)
\r
370 foreach ( object obj in this )
\r
371 array.SetValue( obj, i++ );
\r
374 // IEnumerable Interface
\r
375 public IEnumerator GetEnumerator()
\r
377 return new ListEntryCollectionEnumerator(dict, isKeyList);
\r
380 private class ListEntryCollectionEnumerator : IEnumerator
\r
382 private ListDictionary dict;
\r
383 private bool isKeyList;
\r
384 private bool isAtStart;
\r
385 private int version;
\r
386 private ListEntry current;
\r
388 public ListEntryCollectionEnumerator(ListDictionary dict, bool isKeyList)
\r
391 this.isKeyList = isKeyList;
\r
393 version = dict.modCount;
\r
396 private void FailFast()
\r
398 if (version != dict.modCount) {
\r
399 throw new InvalidOperationException(
\r
400 "The Collection's contents changed after this " +
\r
401 "enumerator was instantiated.");
\r
405 public object Current
\r
410 if (isAtStart || current == null) {
\r
411 throw new InvalidOperationException(
\r
412 "Enumerator is positioned before the collection's " +
\r
413 "first element or after the last element.");
\r
416 return isKeyList ? current.key : current.value;
\r
420 public bool MoveNext()
\r
425 current = dict.root;
\r
428 current = current.next;
\r
431 return current != null ? true : false;
\r
434 public void Reset()
\r