2 // System.Web.UI.WebControls.OrderedDictionary.cs
5 // Lluis Sanchez Gual (lluis@novell.com)
7 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System
.Runtime
.Serialization
;
33 namespace System
.Collections
.Specialized
36 public class OrderedDictionary
: IOrderedDictionary
, IDictionary
, ICollection
, IEnumerable
, ISerializable
, IDeserializationCallback
42 SerializationInfo serializationInfo
;
43 IEqualityComparer comparer
;
45 public OrderedDictionary ()
47 list
= new ArrayList ();
48 hash
= new Hashtable ();
51 public OrderedDictionary (int capacity
)
53 initialCapacity
= (capacity
< 0) ? 0 : capacity
;
54 list
= new ArrayList (initialCapacity
);
55 hash
= new Hashtable (initialCapacity
);
58 public OrderedDictionary (IEqualityComparer equalityComparer
)
60 list
= new ArrayList ();
61 hash
= new Hashtable (equalityComparer
);
62 comparer
= equalityComparer
;
65 public OrderedDictionary (int capacity
, IEqualityComparer equalityComparer
)
67 initialCapacity
= (capacity
< 0) ? 0 : capacity
;
68 list
= new ArrayList (initialCapacity
);
69 hash
= new Hashtable (initialCapacity
, equalityComparer
);
70 comparer
= equalityComparer
;
73 protected OrderedDictionary (SerializationInfo info
, StreamingContext context
)
75 serializationInfo
= info
;
78 protected virtual void OnDeserialization (object sender
)
80 ((IDeserializationCallback
) this).OnDeserialization (sender
);
83 void IDeserializationCallback
.OnDeserialization (object sender
)
85 if (serializationInfo
== null)
88 comparer
= (IEqualityComparer
) serializationInfo
.GetValue ("KeyComparer", typeof (IEqualityComparer
));
89 readOnly
= serializationInfo
.GetBoolean ("ReadOnly");
90 initialCapacity
= serializationInfo
.GetInt32 ("InitialCapacity");
93 list
= new ArrayList ();
97 hash
= new Hashtable (comparer
);
98 object[] array
= (object[]) serializationInfo
.GetValue ("ArrayList", typeof(object[]));
99 foreach (DictionaryEntry de
in array
) {
100 hash
.Add (de
.Key
, de
.Value
);
105 public virtual void GetObjectData (SerializationInfo info
, StreamingContext context
)
108 throw new ArgumentNullException ("info");
110 info
.AddValue ("KeyComparer", comparer
, typeof (IEqualityComparer
));
111 info
.AddValue ("ReadOnly", readOnly
);
112 info
.AddValue ("InitialCapacity", initialCapacity
);
114 object[] array
= new object [hash
.Count
];
115 hash
.CopyTo (array
, 0);
116 info
.AddValue ("ArrayList", array
);
119 IEnumerator IEnumerable
.GetEnumerator()
121 return list
.GetEnumerator ();
130 bool ICollection
.IsSynchronized
{
132 return list
.IsSynchronized
;
136 object ICollection
.SyncRoot
{
138 return list
.SyncRoot
;
142 public void CopyTo (Array array
, int index
)
144 list
.CopyTo (array
, index
);
147 bool IDictionary
.IsFixedSize
{
153 public bool IsReadOnly
160 public object this [object key
]
162 get { return hash [key]; }
165 if (hash
.Contains (key
)) {
166 int i
= FindListEntry (key
);
167 list
[i
] = new DictionaryEntry (key
, value);
169 list
.Add (new DictionaryEntry (key
, value));
175 public object this [int index
]
177 get { return ((DictionaryEntry) list [index]).Value; }
180 DictionaryEntry de
= (DictionaryEntry
) list
[index
];
182 // update (even on the list) isn't automatic
184 hash
[de
.Key
] = value;
188 public ICollection Keys
191 return new OrderedCollection (list
, true);
195 public ICollection Values
198 return new OrderedCollection (list
, false);
202 public void Add (object key
, object value)
205 hash
.Add (key
, value);
206 list
.Add (new DictionaryEntry (key
, value));
216 public bool Contains (object key
)
218 return hash
.Contains (key
);
221 public virtual IDictionaryEnumerator
GetEnumerator()
223 return new OrderedEntryCollectionEnumerator (list
.GetEnumerator ());
226 public void Remove (object key
)
230 if (hash
.Contains (key
)) {
232 int i
= FindListEntry (key
);
237 int FindListEntry (object key
)
239 for (int n
=0; n
<list
.Count
; n
++) {
240 DictionaryEntry de
= (DictionaryEntry
) list
[n
];
241 if (comparer
!= null ? comparer
.Equals(de
.Key
, key
) : de
.Key
.Equals(key
))
250 throw new NotSupportedException ("Collection is read only");
253 public OrderedDictionary
AsReadOnly ()
255 OrderedDictionary od
= new OrderedDictionary ();
258 od
.comparer
= comparer
;
263 public void Insert (int index
, object key
, object value)
266 hash
.Add (key
, value);
267 list
.Insert (index
, new DictionaryEntry (key
, value));
270 public void RemoveAt (int index
)
273 DictionaryEntry entry
= (DictionaryEntry
) list
[index
];
274 list
.RemoveAt (index
);
275 hash
.Remove (entry
.Key
);
278 private class OrderedEntryCollectionEnumerator
: IEnumerator
, IDictionaryEnumerator
280 IEnumerator listEnumerator
;
282 public OrderedEntryCollectionEnumerator (IEnumerator listEnumerator
)
284 this.listEnumerator
= listEnumerator
;
287 public bool MoveNext()
289 return listEnumerator
.MoveNext ();
294 listEnumerator
.Reset ();
297 public object Current
299 get { return listEnumerator.Current; }
302 public DictionaryEntry Entry
304 get { return (DictionaryEntry) listEnumerator.Current; }
309 get { return Entry.Key; }
314 get { return Entry.Value; }
318 private class OrderedCollection
: ICollection
320 private ArrayList list
;
321 private bool isKeyList
;
323 public OrderedCollection (ArrayList list
, bool isKeyList
)
326 this.isKeyList
= isKeyList
;
335 public bool IsSynchronized
342 public object SyncRoot
345 return list
.SyncRoot
;
349 public void CopyTo (Array array
, int index
)
351 for (int n
=0; n
<list
.Count
; n
++) {
352 DictionaryEntry de
= (DictionaryEntry
) list
[n
];
353 if (isKeyList
) array
.SetValue (de
.Key
, index
+ n
);
354 else array
.SetValue (de
.Value
, index
+ n
);
358 public IEnumerator
GetEnumerator()
360 return new OrderedCollectionEnumerator (list
.GetEnumerator (), isKeyList
);
363 private class OrderedCollectionEnumerator
: IEnumerator
365 private bool isKeyList
;
366 IEnumerator listEnumerator
;
368 public OrderedCollectionEnumerator (IEnumerator listEnumerator
, bool isKeyList
)
370 this.listEnumerator
= listEnumerator
;
371 this.isKeyList
= isKeyList
;
374 public object Current
377 DictionaryEntry entry
= (DictionaryEntry
) listEnumerator
.Current
;
378 return isKeyList
? entry
.Key
: entry
.Value
;
382 public bool MoveNext()
384 return listEnumerator
.MoveNext ();
389 listEnumerator
.Reset ();