2002-07-02 Nick Drochak <ndrochak@gol.com>
[mono.git] / mcs / class / corlib / System.Collections / SortedList.cs
1 // \r
2 // System.Collections.SortedList\r
3 // \r
4 // Author:\r
5 //   Sergey Chaban (serge@wildwestsoftware.com)\r
6 // \r
7 \r
8 \r
9 using System;\r
10 using System.Collections;\r
11 \r
12 namespace System.Collections {\r
13 \r
14         /// <summary>\r
15         ///  Represents a collection of associated keys and values\r
16         ///  that are sorted by the keys and are accessible by key\r
17         ///  and by index.\r
18         /// </summary>\r
19         [Serializable]\r
20         public class SortedList : IDictionary, ICollection,\r
21                                   IEnumerable, ICloneable {\r
22 \r
23 \r
24                 internal struct Slot {\r
25                         internal Object key;\r
26                         internal Object value;\r
27                 }\r
28 \r
29                 private readonly static int INITIAL_SIZE = 16;\r
30 \r
31                 public enum EnumeratorMode : int {KEY_MODE = 0, VALUE_MODE}\r
32 \r
33                 private int inUse;\r
34                 private int modificationCount;\r
35                 private Slot[] table;\r
36                 private IComparer comparer;\r
37 \r
38                 //\r
39                 // Constructors\r
40                 //\r
41                 public SortedList () : this (INITIAL_SIZE)\r
42                 {\r
43                 }\r
44 \r
45                 public SortedList (int initialCapacity)\r
46                         : this (null, initialCapacity)\r
47                 {\r
48                 }\r
49 \r
50                 public SortedList (IComparer comparer, int initialCapacity)\r
51                 {\r
52                         if (initialCapacity < 0)\r
53                                 throw new ArgumentOutOfRangeException();\r
54 \r
55                         this.comparer = comparer;\r
56                         InitTable (initialCapacity, true);\r
57                 }\r
58 \r
59                 public SortedList (IComparer comparer)\r
60                 {\r
61                         this.comparer = comparer;\r
62                         InitTable (INITIAL_SIZE, true);\r
63                 }\r
64 \r
65 \r
66                 public SortedList (IDictionary d) : this (d, null)\r
67                 {\r
68                 }\r
69 \r
70                 public SortedList (IDictionary d, IComparer comparer)\r
71                 {\r
72                         if (d  ==  null)\r
73                                 throw new ArgumentNullException ("dictionary");\r
74 \r
75                         InitTable (d.Count, true);\r
76                         this.comparer = comparer;\r
77 \r
78                         IDictionaryEnumerator it = d.GetEnumerator ();\r
79                         while (it.MoveNext ()) {\r
80                                 if (it.Key is IComparable) {\r
81                                         Add (it.Key, it.Value);\r
82                                 } else {\r
83                                         throw new InvalidCastException("!IComparable");\r
84                                 }\r
85                         }\r
86                 }\r
87 \r
88                 //\r
89                 // Properties\r
90                 //\r
91 \r
92                 // ICollection\r
93 \r
94                 public virtual int Count {\r
95                         get {\r
96                                 return inUse;\r
97                         }\r
98                 }\r
99 \r
100                 public virtual bool IsSynchronized {\r
101                         get {\r
102                                 return false;\r
103                         }\r
104                 }\r
105 \r
106                 public virtual Object SyncRoot {\r
107                         get {\r
108                                 return this;\r
109                         }\r
110                 }\r
111 \r
112 \r
113                 // IDictionary\r
114 \r
115                 public virtual bool IsFixedSize {\r
116                         get {\r
117                                 return false;\r
118                         }\r
119                 }\r
120 \r
121 \r
122                 public virtual bool IsReadOnly {\r
123                         get {\r
124                                 return false;\r
125                         }\r
126                 }\r
127 \r
128                 public virtual ICollection Keys {\r
129                         get {\r
130                                 return new ListKeys (this);\r
131                         }\r
132                 }\r
133 \r
134                 public virtual ICollection Values {\r
135                         get {\r
136                                 return new ListValues (this);\r
137                         }\r
138                 }\r
139 \r
140 \r
141 \r
142                 public virtual Object this [Object key] {\r
143                         get {\r
144                                 if (key == null)\r
145                                         throw new ArgumentNullException();\r
146                                 return GetImpl (key);\r
147                         }\r
148                         set {\r
149                                 if (key == null)\r
150                                         throw new ArgumentNullException();\r
151                                 if (IsReadOnly)\r
152                                         throw new NotSupportedException("SortedList is Read Only.");\r
153                                 if (Find(key) < 0 && IsFixedSize)\r
154                                         throw new NotSupportedException("Key not found and SortedList is fixed size.");\r
155 \r
156                                 PutImpl (key, value, true);\r
157                         }\r
158                 }\r
159 \r
160                 public virtual int Capacity {\r
161                         get {\r
162                                 return table.Length;\r
163                         }\r
164                         set {\r
165                                 Slot [] table = this.table;\r
166                                 int current = table.Length;\r
167 \r
168                                 if (inUse > value)\r
169                                         throw new ArgumentOutOfRangeException("capacity too small");\r
170 \r
171                                 if (value > current) {\r
172                                         Slot [] newTable = new Slot [value];\r
173                                         Array.Copy (table, newTable, current);\r
174                                         this.table = newTable;\r
175                                 }\r
176                         }\r
177                 }\r
178 \r
179                 //\r
180                 // Public instance methods.\r
181                 //\r
182 \r
183                 // IEnumerable\r
184 \r
185                 IEnumerator IEnumerable.GetEnumerator ()\r
186                 {\r
187                         return new Enumerator (this, EnumeratorMode.KEY_MODE);\r
188                 }\r
189 \r
190 \r
191                 // IDictionary\r
192 \r
193                 public virtual void Add (object key, object value)\r
194                 {\r
195                         PutImpl (key, value, false);\r
196                 }\r
197 \r
198 \r
199                 public virtual void Clear () \r
200                 {\r
201                         this.table = new Slot [INITIAL_SIZE];\r
202                         inUse = 0;\r
203                         modificationCount++;\r
204                 }\r
205 \r
206                 public virtual bool Contains (object key)\r
207                 {\r
208                         if (null == key)\r
209                                 throw new ArgumentNullException();\r
210 \r
211                         try {\r
212                                 return (Find (key) >= 0);\r
213                         } catch (Exception) {\r
214                                 throw new InvalidOperationException();\r
215                         }\r
216                 }\r
217 \r
218 \r
219                 public virtual IDictionaryEnumerator GetEnumerator ()\r
220                 {\r
221                         return new Enumerator (this, EnumeratorMode.KEY_MODE);\r
222                 }\r
223 \r
224                 public virtual void Remove (object key)\r
225                 {\r
226                         int i = IndexOfKey (key);\r
227                         if (i >= 0) RemoveAt (i);\r
228                 }\r
229 \r
230 \r
231                 // ICollection\r
232 \r
233                 public virtual void CopyTo (Array array, int arrayIndex)\r
234                 {\r
235                         if (null == array)\r
236                                 throw new ArgumentNullException();\r
237 \r
238                         if (arrayIndex < 0)\r
239                                 throw new ArgumentOutOfRangeException();\r
240                         \r
241                         if (array.Rank > 1)\r
242                                 throw new ArgumentException("array is multi-dimensional");\r
243                         if (arrayIndex >= array.Length)\r
244                                 throw new ArgumentNullException("arrayIndex is greater than or equal to array.Length");\r
245                         if (Count > (array.Length - arrayIndex))\r
246                                 throw new ArgumentNullException("Not enough space in array from arrayIndex to end of array");\r
247 \r
248                         IDictionaryEnumerator it = GetEnumerator ();\r
249                         int i = arrayIndex;\r
250 \r
251                         while (it.MoveNext ()) {\r
252                                 array.SetValue (it.Entry, i++);\r
253                         }\r
254                 }\r
255 \r
256 \r
257 \r
258                 // ICloneable\r
259 \r
260                 public virtual object Clone ()\r
261                 {\r
262                         SortedList sl = new SortedList (this, comparer);\r
263                         sl.modificationCount = this.modificationCount;\r
264                         return sl;\r
265                 }\r
266 \r
267 \r
268 \r
269 \r
270                 //\r
271                 // SortedList\r
272                 //\r
273 \r
274                 public virtual IList GetKeyList ()\r
275                 {\r
276                         return new ListKeys (this);\r
277                 }\r
278 \r
279 \r
280                 public virtual IList GetValueList ()\r
281                 {\r
282                         return new ListValues (this);\r
283                 }\r
284 \r
285 \r
286                 public virtual void RemoveAt (int index)\r
287                 {\r
288                         Slot [] table = this.table;\r
289                         int cnt = Count;\r
290                         if (index >= 0 && index < cnt) {\r
291                                 if (index != cnt - 1) {\r
292                                         Array.Copy (table, index+1, table, index, cnt-1-index);\r
293                                 } else {\r
294                                         table [index].key = null;\r
295                                         table [index].value = null;\r
296                                 }\r
297                                 --inUse;\r
298                                 ++modificationCount;\r
299                         } else {\r
300                                 throw new ArgumentOutOfRangeException("index out of range");\r
301                         }\r
302                 }\r
303 \r
304                 public virtual int IndexOfKey (object key)\r
305                 {\r
306                         if (null == key)\r
307                                 throw new ArgumentNullException();\r
308 \r
309                         int indx = 0;\r
310                         try {\r
311                                 indx = Find (key);\r
312                         } catch (Exception) {\r
313                                 throw new InvalidOperationException();\r
314                         }\r
315 \r
316                         return (indx | (indx >> 31));\r
317                 }\r
318 \r
319 \r
320                 public virtual int IndexOfValue (object value)\r
321                 {\r
322                         if (null == value)\r
323                                 return -1;\r
324 \r
325                         Slot [] table = this.table;\r
326                         int len = table.Length;\r
327 \r
328                         for (int i=0; i < len; i++) {\r
329                                 object trial_value = table[i].value;\r
330                                 if ((null != trial_value) && (trial_value.Equals (value))) {\r
331                                         return i;\r
332                                 }\r
333                         }\r
334 \r
335                         return -1;\r
336                 }\r
337 \r
338 \r
339                 public virtual bool ContainsKey (object key)\r
340                 {\r
341                         if (null == key)\r
342                                 throw new ArgumentNullException();\r
343 \r
344                         try {\r
345                                 return Contains (key);   \r
346                         } catch (Exception) {\r
347                                 throw new InvalidOperationException();\r
348                         }\r
349                 }\r
350 \r
351 \r
352                 public virtual bool ContainsValue (object value)\r
353                 {\r
354                         return IndexOfValue (value) >= 0;\r
355                 }\r
356 \r
357 \r
358                 public virtual object GetByIndex (int index)\r
359                 {\r
360                         if (index >= 0 && index < Count) {\r
361                                 return table [index].value;\r
362                         } else {\r
363                                 throw new ArgumentOutOfRangeException("index out of range");\r
364                         }\r
365                 }\r
366 \r
367 \r
368                 public virtual void SetByIndex (int index, object value)\r
369                 {\r
370                         if (index >= 0 && index < Count) {\r
371                                 table [index].value = value;\r
372                         } else {\r
373                                 throw new ArgumentOutOfRangeException("index out of range");\r
374                         }\r
375                 }\r
376 \r
377 \r
378                 public virtual object GetKey (int index)\r
379                 {\r
380                         if (index >= 0 && index < Count) {\r
381                                 return table [index].key;\r
382                         } else {\r
383                                 throw new ArgumentOutOfRangeException("index out of range");\r
384                         }\r
385                 }\r
386 \r
387                 [MonoTODO]\r
388                 public static SortedList Synchronized (SortedList list)\r
389                 {\r
390                         return null;\r
391                 }\r
392 \r
393                 public virtual void TrimToSize ()\r
394                 {\r
395                         // From Beta2:\r
396                         // Trimming an empty SortedList sets the capacity\r
397                         // of the SortedList to the default capacity,\r
398                         // not zero.\r
399                         if (Count == 0) Resize (INITIAL_SIZE, false);\r
400                         else Resize (Count, true);\r
401                 }\r
402 \r
403 \r
404                 //\r
405                 // Private methods\r
406                 //\r
407 \r
408 \r
409                 private void Resize (int n, bool copy)\r
410                 {\r
411                         Slot [] table = this.table;\r
412                         Slot [] newTable = new Slot [n];\r
413                         if (copy) Array.Copy (table, 0, newTable, 0, n);\r
414                         this.table = newTable;\r
415                 }\r
416 \r
417 \r
418                 private void EnsureCapacity (int n, int free)\r
419                 {\r
420                         Slot [] table = this.table;\r
421                         Slot [] newTable = null;\r
422                         int cap = Capacity;\r
423                         bool gap = (free >=0 && free < Count);\r
424 \r
425                         if (n > cap) {\r
426                                 newTable = new Slot [n << 1];\r
427                         }\r
428 \r
429                         if (newTable != null) {\r
430                                 if (gap) {\r
431                                         int copyLen = free;\r
432                                         if (copyLen > 0) {\r
433                                                 Array.Copy (table, 0, newTable, 0, copyLen);\r
434                                         }\r
435                                         copyLen = Count - free;\r
436                                         if (copyLen > 0) {\r
437                                                 Array.Copy (table, free, newTable, free+1, copyLen);\r
438                                         }\r
439                                 } else {\r
440                                         // Just a resizing, copy the entire table.\r
441                                         Array.Copy (table, newTable, Count);\r
442                                 }\r
443                                 this.table = newTable;\r
444                         } else if (gap) {\r
445                                 Array.Copy (table, free, table, free+1, Count - free);\r
446                         }\r
447                 }\r
448 \r
449 \r
450                 private void PutImpl (object key, object value, bool overwrite)\r
451                 {\r
452                         if (key == null)\r
453                                 throw new ArgumentNullException ("null key");\r
454 \r
455                         Slot [] table = this.table;\r
456 \r
457                         int freeIndx = -1;\r
458 \r
459                         try {\r
460                                 freeIndx = Find (key);\r
461                         } catch (Exception) {\r
462                                 throw new InvalidOperationException();\r
463                         }\r
464 \r
465                         if (freeIndx >= 0) {\r
466                                 if (!overwrite)\r
467                                         throw new ArgumentException("element already exists");\r
468 \r
469                                 table [freeIndx].value = value;\r
470                                 return;\r
471                         }\r
472 \r
473                         freeIndx = ~freeIndx;\r
474 \r
475                         if (freeIndx > Capacity + 1)\r
476                                 throw new Exception ("SortedList::internal error ("+key+", "+value+") at ["+freeIndx+"]");\r
477 \r
478 \r
479                         EnsureCapacity (Count+1, freeIndx);\r
480 \r
481                         table = this.table;\r
482                         table [freeIndx].key = key;\r
483                         table [freeIndx].value = value;\r
484 \r
485                         ++inUse;\r
486                         ++modificationCount;\r
487 \r
488                 }\r
489 \r
490 \r
491                 private object GetImpl (object key)\r
492                 {\r
493                         int i = Find (key);\r
494 \r
495                         if (i >= 0)\r
496                                 return table [i].value;\r
497                         else\r
498                                 return null;\r
499                 }\r
500 \r
501                 private void InitTable (int capacity)\r
502                 {\r
503                         InitTable (capacity, false);\r
504                 }\r
505 \r
506                 private void InitTable (int capacity, bool force_size) {\r
507                         if (!force_size && (capacity < INITIAL_SIZE)) capacity = INITIAL_SIZE;\r
508                         this.table = new Slot [capacity];\r
509                         this.inUse = 0;\r
510                         this.modificationCount = 0;\r
511                 }\r
512 \r
513                 private void  CopyToArray (Array arr, int i, \r
514                                            EnumeratorMode mode)\r
515                 {\r
516                         IEnumerator it = new Enumerator (this, mode);\r
517 \r
518                         while (it.MoveNext ()) {\r
519                                 arr.SetValue (it.Current, i++);\r
520                         }\r
521                 }\r
522 \r
523 \r
524                 private int Find (object key)\r
525                 {\r
526                         Slot [] table = this.table;\r
527                         int len = Count;\r
528 \r
529                         if (len == 0) return ~0;\r
530 \r
531                         IComparer comparer = (this.comparer == null)\r
532                                               ? Comparer.Default\r
533                                               : this.comparer;\r
534 \r
535                         int left = 0;\r
536                         int right = len-1;\r
537 \r
538                         while (left <= right) {\r
539                                 int guess = (left + right) >> 1;\r
540 \r
541                                 int cmp = comparer.Compare (key, table[guess].key);\r
542                                 if (cmp == 0) return guess;\r
543 \r
544                                 if (cmp >  0) left = guess+1;\r
545                                 else right = guess-1;\r
546                         }\r
547 \r
548                         return ~left;\r
549                 }\r
550 \r
551 \r
552 \r
553                 //\r
554                 // Inner classes\r
555                 //\r
556 \r
557 \r
558                 protected sealed class Enumerator : IDictionaryEnumerator,\r
559                                                     IEnumerator {\r
560 \r
561                         private SortedList host;\r
562                         private int stamp;\r
563                         private int pos;\r
564                         private int size;\r
565                         private EnumeratorMode mode;\r
566 \r
567                         private object currentKey;\r
568                         private object currentValue;\r
569 \r
570                         private readonly static string xstr = "SortedList.Enumerator: snapshot out of sync.";\r
571 \r
572                         public Enumerator (SortedList host, EnumeratorMode mode)\r
573                         {\r
574                                 this.host = host;\r
575                                 stamp = host.modificationCount;\r
576                                 size = host.Count;\r
577                                 this.mode = mode;\r
578                                 Reset ();\r
579                         }\r
580 \r
581                         public Enumerator (SortedList host)\r
582                                    : this (host, EnumeratorMode.KEY_MODE)\r
583                         {\r
584                         }\r
585 \r
586 \r
587                         private void FailFast ()\r
588                         {\r
589                                 if (host.modificationCount != stamp) {\r
590                                         throw new InvalidOperationException (xstr);\r
591                                 }\r
592                         }\r
593 \r
594                         public void Reset ()\r
595                         {\r
596                                 FailFast ();\r
597 \r
598                                 pos = -1;\r
599                                 currentKey = null;\r
600                                 currentValue = null;\r
601                         }\r
602 \r
603                         public bool MoveNext ()\r
604                         {\r
605                                 FailFast ();\r
606 \r
607                                 Slot [] table = host.table;\r
608 \r
609                                 if (++pos < size) {\r
610                                         Slot entry = table [pos];\r
611 \r
612                                         currentKey = entry.key;\r
613                                         currentValue = entry.value;\r
614                                         return true;\r
615                                 }\r
616 \r
617                                 currentKey = null;\r
618                                 currentValue = null;\r
619                                 return false;\r
620                         }\r
621 \r
622                         public DictionaryEntry Entry\r
623                         {\r
624                                 get {\r
625                                         FailFast ();\r
626                                         return new DictionaryEntry (currentKey,\r
627                                                                     currentValue);\r
628                                 }\r
629                         }\r
630 \r
631                         public Object Key {\r
632                                 get {\r
633                                         FailFast ();\r
634                                         return currentKey;\r
635                                 }\r
636                         }\r
637 \r
638                         public Object Value {\r
639                                 get {\r
640                                         FailFast ();\r
641                                         return currentValue;\r
642                                 }\r
643                         }\r
644 \r
645                         public Object Current {\r
646                                 get {\r
647                                         FailFast ();\r
648                                         return (mode == EnumeratorMode.KEY_MODE)\r
649                                                 ? currentKey\r
650                                                 : currentValue;\r
651                                 }\r
652                         }\r
653                 }\r
654 \r
655 \r
656                 protected class ListKeys : IList, IEnumerable {\r
657 \r
658                         private SortedList host;\r
659 \r
660 \r
661                         public ListKeys (SortedList host)\r
662                         {\r
663                                 if (host == null)\r
664                                         throw new ArgumentNullException ();\r
665 \r
666                                 this.host = host;\r
667                         }\r
668 \r
669                         //\r
670                         // ICollection\r
671                         //\r
672 \r
673                         public virtual int Count {\r
674                                 get {\r
675                                         return host.Count;\r
676                                 }\r
677                         }\r
678 \r
679                         public virtual bool IsSynchronized {\r
680                                 get {\r
681                                         return host.IsSynchronized;\r
682                                 }\r
683                         }\r
684 \r
685                         public virtual Object SyncRoot {\r
686                                 get {\r
687                                         return host.SyncRoot;\r
688                                 }\r
689                         }\r
690 \r
691                         public virtual void CopyTo (Array array, int arrayIndex)\r
692                         {\r
693                                 host.CopyToArray (array, arrayIndex, EnumeratorMode.KEY_MODE);\r
694                         }\r
695 \r
696 \r
697                         //\r
698                         // IList\r
699                         //\r
700 \r
701                         public virtual bool IsFixedSize {\r
702                                 get {\r
703                                         return true;\r
704                                 }\r
705                         }\r
706 \r
707                         public virtual bool IsReadOnly {\r
708                                 get {\r
709                                         return true;\r
710                                 }\r
711                         }\r
712 \r
713 \r
714                         public virtual object this [int index] {\r
715                                 get {\r
716                                         return host.GetKey (index);\r
717                                 }\r
718                                 set {\r
719                                         throw new NotSupportedException("attempt to modify a key");\r
720                                 }\r
721                         }\r
722 \r
723                         public virtual int Add (object value)\r
724                         {\r
725                                 throw new NotSupportedException("IList::Add not supported");\r
726                         }\r
727 \r
728                         public virtual void Clear ()\r
729                         {\r
730                                 throw new NotSupportedException("IList::Clear not supported");\r
731                         }\r
732 \r
733                         public virtual bool Contains (object key)\r
734                         {\r
735                                 return host.Contains (key);\r
736                         }\r
737 \r
738 \r
739                         public virtual int IndexOf (object key)\r
740                         {\r
741                                 return host.IndexOfKey (key);\r
742                         }\r
743 \r
744 \r
745                         public virtual void Insert (int index, object value)\r
746                         {\r
747                                 throw new NotSupportedException("IList::Insert not supported");\r
748                         }\r
749 \r
750 \r
751                         public virtual void Remove (object value)\r
752                         {\r
753                                 throw new NotSupportedException("IList::Remove not supported");\r
754                         }\r
755 \r
756 \r
757                         public virtual void RemoveAt (int index)\r
758                         {\r
759                                 throw new NotSupportedException("IList::RemoveAt not supported");\r
760                         }\r
761 \r
762 \r
763                         //\r
764                         // IEnumerable\r
765                         //\r
766 \r
767                         public virtual IEnumerator GetEnumerator ()\r
768                         {\r
769                                 return new SortedList.Enumerator (host, EnumeratorMode.KEY_MODE);\r
770                         }\r
771 \r
772 \r
773                 }\r
774 \r
775 \r
776                 protected class ListValues : IList, IEnumerable {\r
777 \r
778                         private SortedList host;\r
779 \r
780 \r
781                         public ListValues (SortedList host)\r
782                         {\r
783                                 if (host == null)\r
784                                         throw new ArgumentNullException ();\r
785 \r
786                                 this.host = host;\r
787                         }\r
788 \r
789                         //\r
790                         // ICollection\r
791                         //\r
792 \r
793                         public virtual int Count {\r
794                                 get {\r
795                                         return host.Count;\r
796                                 }\r
797                         }\r
798 \r
799                         public virtual bool IsSynchronized {\r
800                                 get {\r
801                                         return host.IsSynchronized;\r
802                                 }\r
803                         }\r
804 \r
805                         public virtual Object SyncRoot {\r
806                                 get {\r
807                                         return host.SyncRoot;\r
808                                 }\r
809                         }\r
810 \r
811                         public virtual void CopyTo (Array array, int arrayIndex)\r
812                         {\r
813                                 host.CopyToArray (array, arrayIndex, EnumeratorMode.VALUE_MODE);\r
814                         }\r
815 \r
816 \r
817                         //\r
818                         // IList\r
819                         //\r
820 \r
821                         public virtual bool IsFixedSize {\r
822                                 get {\r
823                                         return true;\r
824                                 }\r
825                         }\r
826 \r
827                         public virtual bool IsReadOnly {\r
828                                 get {\r
829                                         return true;\r
830                                 }\r
831                         }\r
832 \r
833 \r
834                         [MonoTODO]\r
835                         public virtual object this [int index] {\r
836                                 get {\r
837                                         return host.GetByIndex (index);\r
838                                 }\r
839                                 set {\r
840                                         // FIXME: It seems (according to tests)\r
841                                         // that modifications are allowed\r
842                                         // in Beta2.\r
843                                         // ? host.SetByIndex (index, value);\r
844                                         throw new NotSupportedException("attempt to modify a value");\r
845                                 }\r
846                         }\r
847 \r
848                         public virtual int Add (object value)\r
849                         {\r
850                                 throw new NotSupportedException("IList::Add not supported");\r
851                         }\r
852 \r
853                         public virtual void Clear ()\r
854                         {\r
855                                 throw new NotSupportedException("IList::Clear not supported");\r
856                         }\r
857 \r
858                         public virtual bool Contains (object value)\r
859                         {\r
860                                 return host.ContainsValue (value);\r
861                         }\r
862 \r
863 \r
864                         public virtual int IndexOf (object value)\r
865                         {\r
866                                 return host.IndexOfValue (value);\r
867                         }\r
868 \r
869 \r
870                         public virtual void Insert (int index, object value)\r
871                         {\r
872                                 throw new NotSupportedException("IList::Insert not supported");\r
873                         }\r
874 \r
875 \r
876                         public virtual void Remove (object value)\r
877                         {\r
878                                 throw new NotSupportedException("IList::Remove not supported");\r
879                         }\r
880 \r
881 \r
882                         public virtual void RemoveAt (int index)\r
883                         {\r
884                                 throw new NotSupportedException("IList::RemoveAt not supported");\r
885                         }\r
886 \r
887 \r
888                         //\r
889                         // IEnumerable\r
890                         //\r
891 \r
892                         public virtual IEnumerator GetEnumerator ()\r
893                         {\r
894                                 return new SortedList.Enumerator (host, EnumeratorMode.VALUE_MODE);\r
895                         }\r
896 \r
897 \r
898                 }\r
899 \r
900         } // SortedList\r
901 \r
902 } // System.Collections\r