Initial commit
[mono.git] / mcs / class / referencesource / System / compmod / system / collections / generic / sorteddictionary.cs
1 namespace System.Collections.Generic {
2     using System;
3     using System.Diagnostics;
4     using System.Diagnostics.CodeAnalysis;
5     using System.Runtime.Serialization;
6        
7 #if !FEATURE_NETCORE
8     [Serializable]
9 #endif
10     [DebuggerTypeProxy(typeof(System_DictionaryDebugView<,>))]
11     [DebuggerDisplay("Count = {Count}")]        
12     public class SortedDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary {
13 #if !FEATURE_NETCORE
14         [NonSerialized]
15 #endif
16         private KeyCollection keys;
17
18 #if !FEATURE_NETCORE
19         [NonSerialized]
20 #endif
21         private ValueCollection values;
22
23         private TreeSet<KeyValuePair<TKey, TValue>> _set;
24
25         public SortedDictionary() : this((IComparer<TKey>)null) {
26         }
27
28         public SortedDictionary(IDictionary<TKey,TValue> dictionary) : this( dictionary, null) {
29         }
30
31         public SortedDictionary(IDictionary<TKey,TValue> dictionary, IComparer<TKey> comparer) {
32             if( dictionary == null) {
33                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
34             }
35
36             _set = new TreeSet<KeyValuePair<TKey, TValue>>(new KeyValuePairComparer(comparer));
37
38             foreach(KeyValuePair<TKey, TValue> pair in dictionary) {
39                 _set.Add(pair);
40             }            
41         }
42
43         public SortedDictionary(IComparer<TKey> comparer) {
44             _set = new TreeSet<KeyValuePair<TKey, TValue>>(new KeyValuePairComparer(comparer));
45         }
46
47         void ICollection<KeyValuePair<TKey,TValue>>.Add(KeyValuePair<TKey,TValue> keyValuePair) {
48             _set.Add(keyValuePair);
49         }
50
51         bool ICollection<KeyValuePair<TKey,TValue>>.Contains(KeyValuePair<TKey,TValue> keyValuePair) {        
52             TreeSet<KeyValuePair<TKey, TValue>>.Node node = _set.FindNode(keyValuePair);
53             if ( node == null) {
54                 return false;
55             }
56
57             if( keyValuePair.Value == null) {
58                 return node.Item.Value == null;
59             }
60             else {
61                 return EqualityComparer<TValue>.Default.Equals(node.Item.Value, keyValuePair.Value);
62             }            
63         }
64
65         bool ICollection<KeyValuePair<TKey,TValue>>.Remove(KeyValuePair<TKey,TValue> keyValuePair) {
66             TreeSet<KeyValuePair<TKey, TValue>>.Node node = _set.FindNode(keyValuePair);
67             if ( node == null) {
68                 return false;
69             }
70
71             if( EqualityComparer<TValue>.Default.Equals(node.Item.Value, keyValuePair.Value)) {
72                 _set.Remove(keyValuePair);
73                 return true;
74             }
75             return false;
76         }
77
78         bool ICollection<KeyValuePair<TKey,TValue>>.IsReadOnly {
79             get {
80                 return false;
81             }
82         }
83
84         public TValue this[TKey key] {
85             get {
86                 if ( key == null) {
87                     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);                    
88                 }
89
90                 TreeSet<KeyValuePair<TKey, TValue>>.Node node = _set.FindNode(new KeyValuePair<TKey, TValue>(key, default(TValue)));
91                 if ( node == null) {
92                     ThrowHelper.ThrowKeyNotFoundException();                    
93                 }
94
95                 return node.Item.Value;
96             }
97             set {
98                 if( key == null) {
99                     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
100                 }
101             
102                 TreeSet<KeyValuePair<TKey, TValue>>.Node node = _set.FindNode(new KeyValuePair<TKey, TValue>(key, default(TValue)));
103                 if ( node == null) {
104                     _set.Add(new KeyValuePair<TKey, TValue>(key, value));                        
105                 } else {
106                     node.Item = new KeyValuePair<TKey, TValue>( node.Item.Key, value);
107                     _set.UpdateVersion();
108                 }
109             }
110         }
111
112         public int Count {
113             get {
114                 return _set.Count;    
115             }
116         }
117
118         public IComparer<TKey> Comparer {
119             get {
120                 return ((KeyValuePairComparer)_set.Comparer).keyComparer;
121             }
122         }
123
124         public KeyCollection Keys {
125             get {
126                 if (keys == null) keys = new KeyCollection(this);
127                 return keys;
128             }
129         }
130
131         ICollection<TKey> IDictionary<TKey, TValue>.Keys {
132             get {                
133                 return Keys;
134             }
135         }
136
137         public ValueCollection Values {
138             get {
139                 if (values == null) values = new ValueCollection(this);
140                 return values;
141             }
142         }
143
144         ICollection<TValue> IDictionary<TKey, TValue>.Values {
145             get {                
146                 return Values;
147             }
148         }
149         
150         public void Add(TKey key, TValue value) {
151             if( key == null) {
152                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
153             }
154             _set.Add(new KeyValuePair<TKey, TValue>(key, value));
155         }
156
157         public void Clear() {
158             _set.Clear();
159         }
160
161         public bool ContainsKey(TKey key) {
162             if( key == null) {
163                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
164             }
165         
166             return _set.Contains(new KeyValuePair<TKey, TValue>(key, default(TValue)));
167         }
168
169         public bool ContainsValue(TValue value) {
170             bool found = false;
171             if( value == null) {
172                 _set.InOrderTreeWalk( delegate(TreeSet<KeyValuePair<TKey, TValue>>.Node node) { 
173                                      if(node.Item.Value == null) {
174                                         found = true;
175                                         return false;  // stop the walk
176                                      }
177                                      return true;
178                                 });
179                 
180             }
181             else {
182                 EqualityComparer<TValue> valueComparer = EqualityComparer<TValue>.Default;
183                 _set.InOrderTreeWalk( delegate(TreeSet<KeyValuePair<TKey, TValue>>.Node node) { 
184                                      if(valueComparer.Equals(node.Item.Value, value)) {
185                                         found = true;
186                                         return false;  // stop the walk
187                                      }
188                                      return true;
189                                 });
190             }
191             return found;
192         }
193
194         public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index) {
195             _set.CopyTo(array, index);
196         }
197
198         public Enumerator GetEnumerator() {
199             return new Enumerator(this, Enumerator.KeyValuePair);
200         }
201
202         IEnumerator<KeyValuePair<TKey,TValue>> IEnumerable<KeyValuePair<TKey,TValue>>.GetEnumerator() {
203             return new Enumerator(this, Enumerator.KeyValuePair);
204         }
205
206         public bool Remove(TKey key) {
207             if( key == null) {
208                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
209             }
210         
211             return _set.Remove(new KeyValuePair<TKey, TValue>(key, default(TValue)));
212         }
213
214         public bool TryGetValue( TKey key, out TValue value) {
215             if( key == null) {
216                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
217             }
218         
219             TreeSet<KeyValuePair<TKey, TValue>>.Node node = _set.FindNode(new KeyValuePair<TKey, TValue>(key, default(TValue)));                
220             if ( node == null) {
221                 value = default(TValue);                    
222                 return false;
223             }
224             value = node.Item.Value;
225             return true;
226         }
227
228         void ICollection.CopyTo(Array array, int index) {
229             ((ICollection)_set).CopyTo(array, index);
230         }
231
232         bool IDictionary.IsFixedSize {
233             get { return false; }
234         }
235
236         bool IDictionary.IsReadOnly {
237             get { return false; }
238         }
239
240         ICollection IDictionary.Keys {
241             get { return (ICollection)Keys; }
242         }
243     
244         ICollection IDictionary.Values {
245             get { return (ICollection)Values; }
246         }
247     
248         object IDictionary.this[object key] {
249             get { 
250                 if( IsCompatibleKey(key)) {               
251                     TValue value;
252                     if( TryGetValue((TKey)key, out value)) {
253                         return value;
254                     }
255                 }
256                 
257                 return null;
258             }
259             set { 
260                 if (key == null)
261                 {
262                     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);                          
263                 }
264
265                 ThrowHelper.IfNullAndNullsAreIllegalThenThrow<TValue>(value, ExceptionArgument.value);
266
267                 try {
268                     TKey tempKey = (TKey)key;
269                     try {
270                         this[tempKey] = (TValue)value; 
271                     }
272                     catch (InvalidCastException) { 
273                         ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(TValue));   
274                     }
275                 }
276                 catch (InvalidCastException) { 
277                     ThrowHelper.ThrowWrongKeyTypeArgumentException(key, typeof(TKey));
278                 }
279             }
280         }
281
282         void IDictionary.Add(object key, object value) {
283             if (key == null)
284             {
285                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);                          
286             }
287
288             ThrowHelper.IfNullAndNullsAreIllegalThenThrow<TValue>(value, ExceptionArgument.value);
289
290             try {
291                 TKey tempKey = (TKey)key;
292
293                 try {
294                     Add(tempKey, (TValue)value);
295                 }
296                 catch (InvalidCastException) { 
297                     ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(TValue));   
298                 }
299             }
300             catch (InvalidCastException) { 
301                 ThrowHelper.ThrowWrongKeyTypeArgumentException(key, typeof(TKey));
302             }
303         }
304     
305         bool IDictionary.Contains(object key) {
306             if(IsCompatibleKey(key)) {
307                 return ContainsKey((TKey)key);
308             }
309             return false;
310         }
311
312         private static bool IsCompatibleKey(object key) {
313             if( key == null) {
314                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);                
315             }
316             
317             return (key is TKey); 
318         }
319
320         IDictionaryEnumerator IDictionary.GetEnumerator() {
321             return new Enumerator(this, Enumerator.DictEntry);
322         }
323     
324         void IDictionary.Remove(object key) {
325             if(IsCompatibleKey(key)) 
326             {
327                 Remove((TKey)key);
328             }
329         }
330
331         bool ICollection.IsSynchronized {
332             get { return false; }
333         }
334
335         object ICollection.SyncRoot { 
336             get { return ((ICollection)_set).SyncRoot; }
337         }
338         
339         IEnumerator IEnumerable.GetEnumerator() {
340             return new Enumerator(this, Enumerator.KeyValuePair);
341         }
342
343         [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "not an expected scenario")]
344         public struct Enumerator : IEnumerator<KeyValuePair<TKey,TValue>>, IDictionaryEnumerator {
345             private TreeSet<KeyValuePair<TKey, TValue>>.Enumerator treeEnum; 
346             private int getEnumeratorRetType;  // What should Enumerator.Current return?
347             
348             internal const int KeyValuePair = 1;
349             internal const int DictEntry = 2;
350
351             internal Enumerator(SortedDictionary<TKey, TValue> dictionary, int getEnumeratorRetType) {
352                 treeEnum = dictionary._set.GetEnumerator();
353                 this.getEnumeratorRetType = getEnumeratorRetType;
354             }
355
356             public bool MoveNext() {
357                 return treeEnum.MoveNext();
358             }
359
360             public void Dispose() {
361                 treeEnum.Dispose();
362             }
363
364             public KeyValuePair<TKey, TValue> Current {
365                 get {
366                     return treeEnum.Current;
367                 }
368             }
369
370             internal bool NotStartedOrEnded {
371                 get {
372                     return treeEnum.NotStartedOrEnded;
373                 }
374             }
375
376             internal void Reset() {
377                 treeEnum.Reset();
378             }
379
380             
381             void IEnumerator.Reset() {
382                 treeEnum.Reset();
383             }
384
385             object IEnumerator.Current {
386                 get {
387                     if( NotStartedOrEnded) {
388                          ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);                        
389                     }
390
391                     if (getEnumeratorRetType == DictEntry) {
392                         return new DictionaryEntry(Current.Key, Current.Value);
393                     } else {
394                         return new KeyValuePair<TKey, TValue>(Current.Key, Current.Value);                        
395                     }           
396
397                 }
398             }
399
400             object IDictionaryEnumerator.Key {
401                 get {
402                     if(NotStartedOrEnded) {
403                          ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);                        
404                     }
405                     
406                     return Current.Key;
407                 }
408             }
409
410             object IDictionaryEnumerator.Value {
411                 get {
412                     if(NotStartedOrEnded) {
413                          ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);                        
414                     }
415                     
416                     return Current.Value;
417                 }
418             }
419
420             DictionaryEntry IDictionaryEnumerator.Entry {
421                 get {
422                     if(NotStartedOrEnded) {
423                          ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);                        
424                     }
425
426                     return new DictionaryEntry(Current.Key, Current.Value);
427                 }
428             }
429         }
430
431         [DebuggerTypeProxy(typeof(System_DictionaryKeyCollectionDebugView<,>))]
432         [DebuggerDisplay("Count = {Count}")]
433 #if !FEATURE_NETCORE
434         [Serializable]
435 #endif
436         public sealed class KeyCollection: ICollection<TKey>, ICollection {
437             private SortedDictionary<TKey,TValue> dictionary;
438
439             public KeyCollection(SortedDictionary<TKey,TValue> dictionary) {
440                 if (dictionary == null) {
441                     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
442                 }
443                 this.dictionary = dictionary;
444             }
445
446             public Enumerator GetEnumerator() {
447                 return new Enumerator(dictionary);
448             }
449             
450             IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator() {
451                 return new Enumerator(dictionary);
452             }
453             
454             IEnumerator IEnumerable.GetEnumerator() {                
455                 return new Enumerator(dictionary);                
456             }
457
458             public void CopyTo(TKey[] array, int index) {
459                 if (array == null) {
460                     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
461                 }
462
463                 if (index < 0) {
464                     ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
465                 }
466
467                 if (array.Length - index < Count) {
468                     ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
469                 }
470
471                 dictionary._set.InOrderTreeWalk( delegate(TreeSet<KeyValuePair<TKey, TValue>>.Node node){ array[index++] = node.Item.Key; return true;});
472             }
473             
474             void ICollection.CopyTo(Array array, int index) {
475                 if (array==null) {
476                     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
477                 }
478
479                 if (array.Rank != 1) {
480                     ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
481                 }
482
483                 if( array.GetLowerBound(0) != 0 ) {
484                     ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
485                 }
486
487                 if (index < 0 ) {
488                     ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.arrayIndex, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
489                 }
490
491                 if (array.Length - index < dictionary.Count) {
492                     ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
493                 }
494                 
495                 TKey[] keys = array as TKey[];
496                 if (keys != null) {
497                     CopyTo(keys, index);
498                 }
499                 else {
500                     object[] objects = (object[])array;
501                     if (objects == null) {
502                         ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
503                     }
504                                          
505                     try {
506                         dictionary._set.InOrderTreeWalk( delegate(TreeSet<KeyValuePair<TKey, TValue>>.Node node){ objects[index++] = node.Item.Key; return true;});
507                     }                    
508                     catch(ArrayTypeMismatchException) {
509                         ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
510                     }
511                 }
512             }
513
514             public int Count {
515                 get { return dictionary.Count;}
516             }
517
518             bool ICollection<TKey>.IsReadOnly {
519                 get { return true;}
520             }
521
522             void ICollection<TKey>.Add(TKey item){
523                 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
524             }
525
526             void ICollection<TKey>.Clear(){
527                 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
528             }
529
530             bool ICollection<TKey>.Contains(TKey item){
531                 return dictionary.ContainsKey(item);
532             }
533
534             bool ICollection<TKey>.Remove(TKey item){
535                 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
536                 return false;
537             }
538
539             bool ICollection.IsSynchronized {
540                 get { return false; }
541             }
542
543             Object ICollection.SyncRoot { 
544                 get { return ((ICollection)dictionary).SyncRoot; }
545             }
546
547             [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "not an expected scenario")]
548             public struct Enumerator : IEnumerator<TKey>, IEnumerator {
549                 private SortedDictionary<TKey, TValue>.Enumerator dictEnum;
550
551                 internal Enumerator(SortedDictionary<TKey, TValue> dictionary) {
552                     dictEnum = dictionary.GetEnumerator();
553                 }
554
555                 public void Dispose() {
556                     dictEnum.Dispose();
557                 }
558
559                 public bool MoveNext() {
560                     return dictEnum.MoveNext();
561                 }
562
563                 public TKey Current {
564                     get {                        
565                         return dictEnum.Current.Key;
566                     }
567                 }
568                 
569                 object IEnumerator.Current {
570                     get {
571                         if( dictEnum.NotStartedOrEnded) {
572                              ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);                        
573                         }
574                         
575                         return Current;
576                     }
577                 }
578
579                 void IEnumerator.Reset() {
580                     dictEnum.Reset();
581                 }
582
583             }                        
584         }
585
586         [DebuggerTypeProxy(typeof(System_DictionaryValueCollectionDebugView<,>))]
587         [DebuggerDisplay("Count = {Count}")]
588 #if !FEATURE_NETCORE
589         [Serializable]
590 #endif
591         public sealed class ValueCollection: ICollection<TValue>, ICollection {
592             private SortedDictionary<TKey,TValue> dictionary;
593
594             public ValueCollection(SortedDictionary<TKey,TValue> dictionary) {
595                 if (dictionary == null) {
596                     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
597                 }
598                 this.dictionary = dictionary;
599             }
600
601             public Enumerator GetEnumerator() {
602                 return new Enumerator(dictionary);
603             }
604
605             IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator() {
606                 return new Enumerator(dictionary);
607             }
608             
609             IEnumerator IEnumerable.GetEnumerator() {                
610                 return new Enumerator(dictionary);                
611             }
612
613             public void CopyTo(TValue[] array, int index) {
614                 if (array == null) {
615                     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
616                 }
617
618                 if (index < 0 ) {
619                     ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
620                 }
621
622                 if (array.Length - index < Count) {
623                     ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
624                 }
625
626                 dictionary._set.InOrderTreeWalk( delegate(TreeSet<KeyValuePair<TKey, TValue>>.Node node){ array[index++] = node.Item.Value; return true;});
627             }
628
629             void ICollection.CopyTo(Array array, int index) {
630                 if (array==null) {
631                     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
632                 }
633
634                 if (array.Rank != 1) {
635                     ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
636                 }
637
638                 if( array.GetLowerBound(0) != 0 ) {
639                     ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
640                 }
641
642                 if (index < 0) {
643                     ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.arrayIndex, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
644                 }
645
646                 if (array.Length - index < dictionary.Count) {
647                     ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
648                 }
649                 
650                 TValue[] values = array as TValue[];
651                 if (values != null) {
652                     CopyTo(values, index);
653                 }
654                 else {
655                     object[] objects = (object[])array;
656                     if (objects == null) {
657                         ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
658                     }
659                                          
660                     try {
661                         dictionary._set.InOrderTreeWalk( delegate(TreeSet<KeyValuePair<TKey, TValue>>.Node node){ objects[index++] = node.Item.Value; return true;});
662                     }                    
663                     catch(ArrayTypeMismatchException) {
664                         ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
665                     }
666                 }
667             }
668
669             public int Count {
670                 get { return dictionary.Count;}
671             }
672
673             bool ICollection<TValue>.IsReadOnly {
674                 get { return true;}
675             }
676
677             void ICollection<TValue>.Add(TValue item){
678                 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
679             }
680
681             void ICollection<TValue>.Clear(){
682                 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
683             }
684
685             bool ICollection<TValue>.Contains(TValue item){
686                 return dictionary.ContainsValue(item);
687             }
688
689             bool ICollection<TValue>.Remove(TValue item){
690                 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
691                 return false;
692             }
693
694             bool ICollection.IsSynchronized {
695                 get { return false; }
696             }
697
698             Object ICollection.SyncRoot { 
699                 get { return ((ICollection)dictionary).SyncRoot; }
700             }
701
702             [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "not an expected scenario")]
703             public struct Enumerator : IEnumerator<TValue>, IEnumerator {
704                 private SortedDictionary<TKey, TValue>.Enumerator dictEnum;
705
706                 internal Enumerator(SortedDictionary<TKey, TValue> dictionary) {
707                     dictEnum = dictionary.GetEnumerator();
708                 }
709
710                 public void Dispose() {
711                     dictEnum.Dispose();
712                 }
713
714                 public bool MoveNext() {
715                     return dictEnum.MoveNext();
716                 }
717
718                 public TValue Current {
719                     get {                        
720                         return dictEnum.Current.Value;
721                     }
722                 }
723
724                 object IEnumerator.Current {
725                     get {
726                         if( dictEnum.NotStartedOrEnded) {
727                              ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);                        
728                         }
729                         
730                         return Current;
731                     }
732                 }
733
734                 void IEnumerator.Reset() {
735                     dictEnum.Reset();
736                 }
737             }                        
738         }
739
740 #if !FEATURE_NETCORE
741         [Serializable]
742 #endif
743         internal class KeyValuePairComparer : Comparer<KeyValuePair<TKey, TValue>> {
744             internal IComparer<TKey> keyComparer;
745
746             public KeyValuePairComparer(IComparer<TKey> keyComparer) {
747                 if ( keyComparer == null) {
748                     this.keyComparer = Comparer<TKey>.Default;                    
749                 } else {
750                     this.keyComparer = keyComparer;
751                 }
752             }
753
754             public  override int Compare( KeyValuePair<TKey, TValue> x, KeyValuePair<TKey, TValue> y) {
755                 return keyComparer.Compare(x.Key, y.Key);
756             }            
757         }
758     }
759
760
761
762     /// <summary>
763     /// This class is intended as a helper for backwards compatibility with existing SortedDictionaries.
764     /// TreeSet has been converted into SortedSet<T>, which will be exposed publicly. SortedDictionaries
765     /// have the problem where they have already been serialized to disk as having a backing class named
766     /// TreeSet. To ensure that we can read back anything that has already been written to disk, we need to
767     /// make sure that we have a class named TreeSet that does everything the way it used to.
768     /// 
769     /// The only thing that makes it different from SortedSet is that it throws on duplicates
770     /// </summary>
771     /// <typeparam name="T"></typeparam>
772 #if !FEATURE_NETCORE
773     [Serializable]
774 #endif
775     internal class TreeSet<T> : SortedSet<T> {
776
777         public TreeSet()
778             : base() { }
779
780         public TreeSet(IComparer<T> comparer) : base(comparer) { }
781
782         public TreeSet(ICollection<T> collection) : base(collection) { }
783
784         public TreeSet(ICollection<T> collection, IComparer<T> comparer) : base(collection, comparer) { }
785
786 #if !FEATURE_NETCORE
787         public TreeSet(SerializationInfo siInfo, StreamingContext context) : base(siInfo, context) { }
788 #endif
789
790         internal override bool AddIfNotPresent(T item) {
791             bool ret = base.AddIfNotPresent(item);
792             if (!ret) {                
793                 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);                
794             }
795             return ret;
796         }
797
798     }
799
800 }