2005-04-21 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / Mono.C5 / Wrappers.cs
1 #if NET_2_0
2 /*
3  Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>
4  Permission is hereby granted, free of charge, to any person obtaining a copy
5  of this software and associated documentation files (the "Software"), to deal
6  in the Software without restriction, including without limitation the rights
7  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  copies of the Software, and to permit persons to whom the Software is
9  furnished to do so, subject to the following conditions:
10  
11  The above copyright notice and this permission notice shall be included in
12  all copies or substantial portions of the Software.
13  
14  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  SOFTWARE.
21 */
22
23 using System;
24 using System.Diagnostics;
25 using MSG = System.Collections.Generic;
26 namespace C5
27 {
28         /// <summary>
29         /// A read-only wrapper class for a generic enumerator
30         /// </summary>
31         public class GuardedEnumerator<T>: MSG.IEnumerator<T>
32         {
33                 #region Fields
34
35                 MSG.IEnumerator<T> enumerator;
36
37                 #endregion
38
39                 #region Constructor
40
41                 /// <summary>
42                 /// Create a wrapper around a generic enumerator
43                 /// </summary>
44                 /// <param name="enumerator">The enumerator to wrap</param>
45                 public GuardedEnumerator(MSG.IEnumerator<T> enumerator)
46                 { this.enumerator = enumerator; }
47
48                 #endregion
49
50                 #region IEnumerator<T> Members
51
52                 /// <summary>
53                 /// Move wrapped enumerator to next item, or the first item if
54                 /// this is the first call to MoveNext. 
55                 /// </summary>
56                 /// <returns>True if enumerator is valid now</returns>
57                 public bool MoveNext() { return enumerator.MoveNext(); }
58
59
60                 /// <summary>
61                 /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
62                 /// </summary>
63                 /// <value>The current item of the wrapped enumerator.</value>
64                 public T Current { get { return enumerator.Current; } }
65
66                 #endregion
67
68                 #region IDisposable Members
69
70                 /// <summary>
71                 /// Dispose wrapped enumerator
72                 /// </summary>
73                 public void Dispose() { enumerator.Dispose(); }
74
75                 #endregion
76         }
77
78
79
80         /// <summary>
81         /// A read-only wrapper class for a generic enumerable
82         ///
83         /// <p>This is mainly interesting as a base of other guard classes</p>
84         /// </summary>
85         public class GuardedEnumerable<T>: MSG.IEnumerable<T>
86         {
87                 #region Fields
88
89                 MSG.IEnumerable<T> enumerable;
90
91                 #endregion
92
93                 #region Constructor
94
95                 /// <summary>
96                 /// Wrap an enumerable in a read-only wrapper
97                 /// </summary>
98                 /// <param name="enumerable">The enumerable to wrap</param>
99                 public GuardedEnumerable(MSG.IEnumerable<T> enumerable)
100                 { this.enumerable = enumerable; }
101
102                 #endregion
103
104                 #region MSG.IEnumerable<T> Members
105
106                 /// <summary>
107                 /// Get an enumerator from the wrapped enumerable
108                 /// </summary>
109                 /// <returns>The enumerator (itself wrapped)</returns>
110                 public MSG.IEnumerator<T> GetEnumerator()
111                 { return new GuardedEnumerator<T>(enumerable.GetEnumerator()); }
112
113                 #endregion
114         }
115
116
117
118         /// <summary>
119         /// A read-only wrapper for a generic directed enumerable
120         ///
121         /// <p>This is mainly interesting as a base of other guard classes</p>
122         /// </summary>
123         public class GuardedDirectedEnumerable<T>: GuardedEnumerable<T>, IDirectedEnumerable<T>
124         {
125                 #region Fields
126
127                 IDirectedEnumerable<T> directedenumerable;
128
129                 #endregion
130
131                 #region Constructor
132
133                 /// <summary>
134                 /// Wrap a directed enumerable in a read-only wrapper
135                 /// </summary>
136                 /// <param name="directedenumerable">the collection to wrap</param>
137                 public GuardedDirectedEnumerable(IDirectedEnumerable<T> directedenumerable)
138                         : base(directedenumerable)
139                 { this.directedenumerable = directedenumerable; }
140
141                 #endregion
142
143                 #region IDirectedEnumerable<T> Members
144
145                 /// <summary>
146                 /// Get a enumerable that enumerates the wrapped collection in the opposite direction
147                 /// </summary>
148                 /// <returns>The mirrored enumerable</returns>
149                 public IDirectedEnumerable<T> Backwards()
150                 { return new GuardedDirectedEnumerable<T>(directedenumerable.Backwards()); }
151
152
153                 /// <summary>
154                 /// <code>Forwards</code> if same, else <code>Backwards</code>
155                 /// </summary>
156                 /// <value>The enumeration direction relative to the original collection.</value>
157                 public EnumerationDirection Direction
158                 { get { return directedenumerable.Direction; } }
159
160                 #endregion
161         }
162
163
164
165         /// <summary>
166         /// A read-only wrapper for an ICollectionValue&lt;T&gt;
167         ///
168         /// <p>This is mainly interesting as a base of other guard classes</p>
169         /// </summary>
170         public class GuardedCollectionValue<T>: GuardedEnumerable<T>, ICollectionValue<T>
171         {
172                 #region Fields
173
174                 ICollectionValue<T> collection;
175
176                 #endregion
177
178                 #region Constructor
179
180                 /// <summary>
181                 /// Wrap a ICollectionValue&lt;T&gt; in a read-only wrapper
182                 /// </summary>
183                 /// <param name="collection">the collection to wrap</param>
184                 public GuardedCollectionValue(ICollectionValue<T> collection) : base(collection)
185                 { this.collection = collection; }
186
187                 #endregion
188
189                 #region ICollection<T> Members
190
191                 /// <summary>
192                 /// Get the size of the wrapped collection
193                 /// </summary>
194                 /// <value>The size</value>
195                 public int Count { get { return collection.Count; } }
196
197         /// <summary>
198         /// The value is symbolic indicating the type of asymptotic complexity
199         /// in terms of the size of this collection (worst-case or amortized as
200         /// relevant).
201         /// </summary>
202         /// <value>A characterization of the speed of the 
203         /// <code>Count</code> property in this collection.</value>
204         public Speed CountSpeed { get { return collection.CountSpeed; } }
205
206         /// <summary>
207                 /// Copy the items of the wrapped collection to an array
208                 /// </summary>
209                 /// <param name="a">The array</param>
210                 /// <param name="i">Starting offset</param>
211                 public void CopyTo(T[] a, int i) { collection.CopyTo(a, i); }
212
213         /// <summary>
214         /// Create an array from the items of the wrapped collection
215         /// </summary>
216         /// <returns>The array</returns>
217         public T[] ToArray() { return collection.ToArray(); }
218
219         /// <summary>
220         /// Apply a delegate to all items of the wrapped enumerable.
221         /// </summary>
222         /// <param name="a">The delegate to apply</param>
223         //TODO: change this to throw an exception?
224         public void Apply(Applier<T> a) { collection.Apply(a); }
225
226
227         /// <summary>
228         /// Check if there exists an item  that satisfies a
229         /// specific predicate in the wrapped enumerable.
230         /// </summary>
231         /// <param name="filter">A filter delegate 
232         /// (<see cref="T:C5.Filter!1"/>) defining the predicate</param>
233         /// <returns>True is such an item exists</returns>
234         public bool Exists(Filter<T> filter) { return collection.Exists(filter); }
235
236
237         /// <summary>
238         /// Check if all items in the wrapped enumerable satisfies a specific predicate.
239         /// </summary>
240         /// <param name="filter">A filter delegate 
241         /// (<see cref="T:C5.Filter!1"/>) defining the predicate</param>
242         /// <returns>True if all items satisfies the predicate</returns>
243         public bool All(Filter<T> filter) { return collection.All(filter); }
244         #endregion
245     }
246
247
248
249         /// <summary>
250         /// A read-only wrapper for a directed collection
251         ///
252         /// <p>This is mainly interesting as a base of other guard classes</p>
253         /// </summary>
254         public class GuardedDirectedCollectionValue<T>: GuardedCollectionValue<T>, IDirectedCollectionValue<T>
255         {
256                 #region Fields
257
258                 IDirectedCollectionValue<T> directedcollection;
259
260                 #endregion
261
262                 #region Constructor
263
264                 /// <summary>
265                 /// Wrap a directed collection in a read-only wrapper
266                 /// </summary>
267                 /// <param name="directedcollection">the collection to wrap</param>
268                 public GuardedDirectedCollectionValue(IDirectedCollectionValue<T> directedcollection) : 
269                         base(directedcollection)
270                 { this.directedcollection = directedcollection; }
271
272                 #endregion
273
274                 #region IDirectedCollection<T> Members
275
276                 /// <summary>
277                 /// Get a collection that enumerates the wrapped collection in the opposite direction
278                 /// </summary>
279                 /// <returns>The mirrored collection</returns>
280                 public IDirectedCollectionValue<T> Backwards()
281                 { return new GuardedDirectedCollectionValue<T>(directedcollection.Backwards()); }
282
283                 #endregion
284
285                 #region IDirectedEnumerable<T> Members
286
287                 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
288                 { return Backwards(); }
289
290
291                 /// <summary>
292                 /// <code>Forwards</code> if same, else <code>Backwards</code>
293                 /// </summary>
294                 /// <value>The enumeration direction relative to the original collection.</value>
295                 public EnumerationDirection Direction
296                 { get { return directedcollection.Direction; } }
297
298                 #endregion
299         }
300
301
302
303         /// <summary>
304         /// A read-only wrapper for an ICollection&lt;T&gt;.
305         /// <see cref="T:C5.ICollection!1"/>
306         ///
307         /// <p>Suitable for wrapping hash tables, <see cref="T:C5.HashSet!1"/>
308         /// and <see cref="T:C5.HashBag!1"/>  </p>
309         /// </summary>
310         public class GuardedCollection<T>: GuardedCollectionValue<T>, ICollection<T>
311         {
312                 #region Fields
313
314                 ICollection<T> collection;
315
316                 #endregion
317
318                 #region Constructor
319
320                 /// <summary>
321                 /// Wrap an ICollection&lt;T&gt; in a read-only wrapper
322                 /// </summary>
323                 /// <param name="collection">the collection to wrap</param>
324                 public GuardedCollection(ICollection<T> collection)
325                         :base(collection)
326                 { this.collection = collection; }
327
328                 #endregion
329
330                 #region ICollection<T> Members
331
332                 /// <summary>
333                 /// (This is a read-only wrapper)
334                 /// </summary>
335                 /// <value>True</value>
336                 public bool IsReadOnly { get { return true; } }
337
338
339                 /// <summary> </summary>
340                 /// <value>Speed of wrapped collection</value>
341                 public Speed ContainsSpeed { get { return collection.ContainsSpeed; } }
342
343
344                 int ICollection<T>.GetHashCode()
345                 { return ((ICollection<T>)collection).GetHashCode(); }
346
347
348                 bool ICollection<T>.Equals(ICollection<T> that)
349                 { return ((ICollection<T>)collection).Equals(that); }
350
351
352                 /// <summary>
353                 /// Check if an item is in the wrapped collection
354                 /// </summary>
355                 /// <param name="item">The item</param>
356                 /// <returns>True if found</returns>
357                 public bool Contains(T item) { return collection.Contains(item); }
358
359
360                 /// <summary>
361                 /// Count the number of times an item appears in the wrapped collection
362                 /// </summary>
363                 /// <param name="item">The item</param>
364                 /// <returns>The number of copies</returns>
365                 public int ContainsCount(T item) { return collection.ContainsCount(item); }
366
367
368                 /// <summary>
369                 /// Check if all items in the argument is in the wrapped collection
370                 /// </summary>
371                 /// <param name="items">The items</param>
372                 /// <returns>True if so</returns>
373                 public bool ContainsAll(MSG.IEnumerable<T> items) { return collection.ContainsAll(items); }
374
375
376                 /// <summary>
377                 /// Search for an item in the wrapped collection
378                 /// </summary>
379                 /// <param name="item">On entry the item to look for, on exit the equivalent item found (if any)</param>
380                 /// <returns></returns>
381                 public bool Find(ref T item) { return collection.Find(ref item); }
382
383
384                 /// <summary>
385                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
386                 /// </summary>
387                 /// <param name="item"></param>
388                 /// <returns></returns>
389                 public bool FindOrAdd(ref T item)
390                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
391
392
393                 /// <summary>
394                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
395                 /// </summary>
396                 /// <param name="item"></param>
397                 /// <returns></returns>
398                 public bool Update(T item)
399                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
400
401
402                 /// <summary>
403                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
404                 /// </summary>
405                 /// <param name="item"></param>
406                 /// <returns></returns>
407                 public bool UpdateOrAdd(T item)
408                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
409
410
411                 /// <summary>
412                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
413                 /// </summary>
414                 /// <param name="item"></param>
415                 /// <returns></returns>
416                 public bool Remove(T item)
417                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
418
419
420                 /// <summary>
421                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
422                 /// </summary>
423                 /// <param name="item"></param>
424                 /// <returns></returns>
425                 public bool RemoveWithReturn(ref T item)
426                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
427
428
429                 /// <summary>
430                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
431                 /// </summary>
432                 /// <param name="item"></param>
433                 public void RemoveAllCopies(T item)
434                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
435
436
437                 /// <summary>
438                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
439                 /// </summary>
440                 /// <param name="items"></param>
441                 public void RemoveAll(MSG.IEnumerable<T> items)
442                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
443
444
445                 /// <summary>
446                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
447                 /// </summary>
448                 public void Clear()
449                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
450
451
452                 /// <summary>
453                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
454                 /// </summary>
455                 /// <param name="items"></param>
456                 public void RetainAll(MSG.IEnumerable<T> items)
457                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
458
459
460                 /// <summary>
461                 /// Check  wrapped collection for internal consistency
462                 /// </summary>
463                 /// <returns>True if check passed</returns>
464                 public bool Check() { return collection.Check(); }
465
466                 #endregion
467
468                 #region ISink<T> Members
469
470                 /// <summary> </summary>
471                 /// <value>False if wrapped collection has set semantics</value>
472         public bool AllowsDuplicates { get { return collection.AllowsDuplicates; } }
473
474
475         /// <summary> </summary>
476                 /// <value>The sync root of the wrapped collection</value>
477                 public object SyncRoot { get { return collection.SyncRoot; } }
478
479
480                 /// <summary> </summary>
481                 /// <value>True if wrapped collection is empty</value>
482                 public bool IsEmpty { get { return collection.IsEmpty; } }
483
484
485                 /// <summary>
486                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
487                 /// </summary>
488                 /// <param name="item"></param>
489                 /// <returns></returns>
490                 public bool Add(T item)
491                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
492
493
494         /// <summary>
495         /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
496         /// </summary>
497         /// <param name="items"></param>
498         public void AddAll(MSG.IEnumerable<T> items)
499         { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
500
501         /// <summary>
502         /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
503         /// </summary>
504         /// <param name="items"></param>
505         /*public*/ void C5.IExtensible<T>.AddAll<U>(MSG.IEnumerable<U> items) //where U : T
506         { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
507
508         #endregion
509     }
510
511
512         /// <summary>
513         /// A read-only wrapper for a sequenced collection
514         ///
515         /// <p>This is mainly interesting as a base of other guard classes</p>
516         /// </summary>
517         public class GuardedSequenced<T>: GuardedCollection<T>, ISequenced<T>
518         {
519                 #region Fields
520
521                 ISequenced<T> sequenced;
522
523                 #endregion
524
525                 #region Constructor
526
527                 /// <summary>
528                 /// Wrap a sequenced collection in a read-only wrapper
529                 /// </summary>
530                 /// <param name="sorted"></param>
531                 public GuardedSequenced(ISequenced<T> sorted):base(sorted) { this.sequenced = sorted; }
532
533                 #endregion
534
535                 #region ISequenced<T> Members
536
537                 int ISequenced<T>.GetHashCode()
538                 { return ((ISequenced<T>)sequenced).GetHashCode(); }
539
540
541                 bool ISequenced<T>.Equals(ISequenced<T> that)
542                 { return ((ISequenced<T>)sequenced).Equals(that); }
543
544                 #endregion
545
546                 #region IEditableCollection<T> Members
547
548                 int ICollection<T>.GetHashCode()
549                 { return ((ICollection<T>)sequenced).GetHashCode(); }
550
551
552                 bool ICollection<T>.Equals(ICollection<T> that)
553                 { return ((ICollection<T>)sequenced).Equals(that); }
554
555                 #endregion
556
557                 #region IDirectedCollection<T> Members
558
559                 /// <summary>
560                 /// Get a collection that enumerates the wrapped collection in the opposite direction
561                 /// </summary>
562                 /// <returns>The mirrored collection</returns>
563                 public IDirectedCollectionValue<T> Backwards()
564                 { return new GuardedDirectedCollectionValue<T>(sequenced.Backwards()); }
565
566                 #endregion
567
568                 #region IDirectedEnumerable<T> Members
569
570                 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
571                 { return Backwards(); }
572
573
574
575                 /// <summary>
576                 /// <code>Forwards</code> if same, else <code>Backwards</code>
577                 /// </summary>
578                 /// <value>The enumeration direction relative to the original collection.</value>
579                 public EnumerationDirection Direction
580                 { get { return EnumerationDirection.Forwards; } }
581
582                 #endregion
583         }
584
585
586
587         /// <summary>
588         /// A read-only wrapper for a sorted collection
589         ///
590         /// <p>This is mainly interesting as a base of other guard classes</p>
591         /// </summary>
592         public class GuardedSorted<T>: GuardedSequenced<T>, ISorted<T>
593         {
594                 #region Fields
595
596                 ISorted<T> sorted;
597
598                 #endregion
599
600                 #region Constructor
601
602                 /// <summary>
603                 /// Wrap a sorted collection in a read-only wrapper
604                 /// </summary>
605                 /// <param name="sorted"></param>
606                 public GuardedSorted(ISorted<T> sorted):base(sorted) { this.sorted = sorted; }
607
608                 #endregion
609
610         #region IEditableCollection Members
611
612                 int ICollection<T>.GetHashCode()
613                 { return ((ICollection<T>)sorted).GetHashCode(); }
614
615
616                 bool ICollection<T>.Equals(ICollection<T> that)
617                 { return ((ICollection<T>)sorted).Equals(that); }
618
619                 #endregion
620
621                 #region ISequenced<T> Members
622
623                 int ISequenced<T>.GetHashCode()
624                 { return ((ISequenced<T>)sorted).GetHashCode(); }
625
626
627                 bool ISequenced<T>.Equals(ISequenced<T> that)
628                 { return ((ISequenced<T>)sorted).Equals(that); }
629
630
631                 #endregion
632
633                 #region ISorted<T> Members
634
635                 /// <summary>
636                 /// Find the predecessor of the item in the wrapped sorted collection
637                 /// </summary>
638                 /// <param name="item">The item</param>
639                 /// <returns>The predecessor</returns>
640                 public T Predecessor(T item) { return sorted.Predecessor(item); }
641
642
643                 /// <summary>
644                 /// Find the Successor of the item in the wrapped sorted collection
645                 /// </summary>
646                 /// <param name="item">The item</param>
647                 /// <returns>The Successor</returns>
648                 public T Successor(T item) { return sorted.Successor(item); }
649
650
651                 /// <summary>
652                 /// Find the weak predecessor of the item in the wrapped sorted collection
653                 /// </summary>
654                 /// <param name="item">The item</param>
655                 /// <returns>The weak predecessor</returns>
656                 public T WeakPredecessor(T item) { return sorted.WeakPredecessor(item); }
657
658
659                 /// <summary>
660                 /// Find the weak Successor of the item in the wrapped sorted collection
661                 /// </summary>
662                 /// <param name="item">The item</param>
663                 /// <returns>The weak Successor</returns>
664                 public T WeakSuccessor(T item) { return sorted.WeakSuccessor(item); }
665
666
667                 /// <summary>
668                 /// Run Cut on the wrapped sorted collection
669                 /// </summary>
670                 /// <param name="c"></param>
671                 /// <param name="low"></param>
672                 /// <param name="lval"></param>
673                 /// <param name="high"></param>
674                 /// <param name="hval"></param>
675                 /// <returns></returns>
676                 public bool Cut(IComparable<T> c, out T low, out bool lval, out T high, out bool hval)
677                 { return sorted.Cut(c, out low, out lval, out high, out hval); }
678
679
680                 /// <summary>
681                 /// Get the specified range from the wrapped collection. 
682                 /// (The current implementation erroneously does not wrap the result.)
683                 /// </summary>
684                 /// <param name="bot"></param>
685                 /// <returns></returns>
686                 public IDirectedEnumerable<T> RangeFrom(T bot) { return sorted.RangeFrom(bot); }
687
688
689                 /// <summary>
690                 /// Get the specified range from the wrapped collection. 
691                 /// (The current implementation erroneously does not wrap the result.)
692                 /// </summary>
693                 /// <param name="bot"></param>
694                 /// <param name="top"></param>
695                 /// <returns></returns>
696                 public IDirectedEnumerable<T> RangeFromTo(T bot, T top)
697                 { return sorted.RangeFromTo(bot, top); }
698
699
700                 /// <summary>
701                 /// Get the specified range from the wrapped collection. 
702                 /// (The current implementation erroneously does not wrap the result.)
703                 /// </summary>
704                 /// <param name="top"></param>
705                 /// <returns></returns>
706                 public IDirectedEnumerable<T> RangeTo(T top) { return sorted.RangeTo(top); }
707
708
709                 /// <summary>
710                 /// Get the specified range from the wrapped collection. 
711                 /// (The current implementation erroneously does not wrap the result.)
712                 /// </summary>
713                 /// <returns></returns>
714                 public IDirectedCollectionValue<T> RangeAll() { return sorted.RangeAll(); }
715
716
717                 /// <summary>
718                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
719                 /// </summary>
720                 /// <param name="items"></param>
721                 public void AddSorted(MSG.IEnumerable<T> items)
722                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
723
724
725                 /// <summary>
726                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
727                 /// </summary>
728                 /// <param name="low"></param>
729                 public void RemoveRangeFrom(T low)
730                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
731
732
733                 /// <summary>
734                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
735                 /// </summary>
736                 /// <param name="low"></param>
737                 /// <param name="hi"></param>
738                 public void RemoveRangeFromTo(T low, T hi)
739                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
740
741
742                 /// <summary>
743                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
744                 /// </summary>
745                 /// <param name="hi"></param>
746                 public void RemoveRangeTo(T hi)
747                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
748
749                 #endregion
750
751                 #region IPriorityQueue<T> Members
752
753                 /// <summary>
754                 /// Find the minimum of the wrapped collection
755                 /// </summary>
756                 /// <returns>The minimum</returns>
757                 public T FindMin() { return sorted.FindMin(); }
758
759
760                 /// <summary>
761                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
762                 /// </summary>
763                 /// <returns></returns>
764                 public T DeleteMin()
765                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
766
767
768                 /// <summary>
769                 /// Find the maximum of the wrapped collection
770                 /// </summary>
771                 /// <returns>The maximum</returns>
772                 public T FindMax() { return sorted.FindMax(); }
773
774
775                 /// <summary>
776                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
777                 /// </summary>
778                 /// <returns></returns>
779                 public T DeleteMax()
780                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
781
782         /// <summary>
783         /// The comparer object supplied at creation time for the underlying collection
784         /// </summary>
785         /// <value>The comparer</value>
786         public IComparer<T> Comparer { get { return sorted.Comparer; } }
787         #endregion
788
789
790                 #region IDirectedEnumerable<T> Members
791
792                 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
793                 { return Backwards(); }
794
795                 #endregion
796         }
797
798
799
800         /// <summary>
801         /// Read-only wrapper for indexed sorted collections
802         ///
803         /// <p>Suitable for wrapping TreeSet, TreeBag and SortedArray</p>
804         /// </summary>
805         public class GuardedIndexedSorted<T>: GuardedSorted<T>, IIndexedSorted<T>
806         {
807                 #region Fields
808
809                 IIndexedSorted<T> indexedsorted;
810
811                 #endregion
812
813                 #region Constructor
814
815                 /// <summary>
816                 /// Wrap an indexed sorted collection in a read-only wrapper
817                 /// </summary>
818                 /// <param name="list">the indexed sorted collection</param>
819                 public GuardedIndexedSorted(IIndexedSorted<T> list):base(list)
820                 { this.indexedsorted = list; }
821
822                 #endregion
823
824                 #region IIndexedSorted<T> Members
825
826                 /// <summary>
827                 /// Get the specified range from the wrapped collection. 
828                 /// (The current implementation erroneously does not wrap the result.)
829                 /// </summary>
830                 /// <param name="bot"></param>
831                 /// <returns></returns>
832                 public new IDirectedCollectionValue<T> RangeFrom(T bot)
833                 { return indexedsorted.RangeFrom(bot); }
834
835
836                 /// <summary>
837                 /// Get the specified range from the wrapped collection. 
838                 /// (The current implementation erroneously does not wrap the result.)
839                 /// </summary>
840                 /// <param name="bot"></param>
841                 /// <param name="top"></param>
842                 /// <returns></returns>
843                 public new IDirectedCollectionValue<T> RangeFromTo(T bot, T top)
844                 { return indexedsorted.RangeFromTo(bot, top); }
845
846
847                 /// <summary>
848                 /// Get the specified range from the wrapped collection. 
849                 /// (The current implementation erroneously does not wrap the result.)
850                 /// </summary>
851                 /// <param name="top"></param>
852                 /// <returns></returns>
853                 public new IDirectedCollectionValue<T> RangeTo(T top)
854                 { return indexedsorted.RangeTo(top); }
855
856
857                 /// <summary>
858                 /// Report the number of items in the specified range of the wrapped collection
859                 /// </summary>
860                 /// <param name="bot"></param>
861                 /// <returns></returns>
862                 public int CountFrom(T bot) { return indexedsorted.CountFrom(bot); }
863
864
865                 /// <summary>
866                 /// Report the number of items in the specified range of the wrapped collection
867                 /// </summary>
868                 /// <param name="bot"></param>
869                 /// <param name="top"></param>
870                 /// <returns></returns>
871                 public int CountFromTo(T bot, T top) { return indexedsorted.CountFromTo(bot, top); }
872
873
874                 /// <summary>
875                 /// Report the number of items in the specified range of the wrapped collection
876                 /// </summary>
877                 /// <param name="top"></param>
878                 /// <returns></returns>
879                 public int CountTo(T top) { return indexedsorted.CountTo(top); }
880
881
882                 /// <summary>
883                 /// Run FindAll on the wrapped collection with the indicated filter.
884                 /// The result will <b>not</b> be read-only.
885                 /// </summary>
886                 /// <param name="f"></param>
887                 /// <returns></returns>
888                 public IIndexedSorted<T> FindAll(Filter<T> f)
889                 { return indexedsorted.FindAll(f); }
890
891
892                 /// <summary>
893                 /// Run Map on the wrapped collection with the indicated mapper.
894                 /// The result will <b>not</b> be read-only.
895                 /// </summary>
896                 /// <param name="m"></param>
897                 /// <param name="c">The comparer to use in the result</param>
898                 /// <returns></returns>
899                 public IIndexedSorted<V> Map<V>(Mapper<T,V> m, IComparer<V> c)
900                 { return indexedsorted.Map<V>(m, c); }
901
902                 #endregion
903
904                 #region IIndexed<T> Members
905
906                 /// <summary>
907                 /// 
908                 /// </summary>
909                 /// <value>The i'th item of the wrapped sorted collection</value>
910                 public T this[int i] { get { return indexedsorted[i]; } }
911
912
913                 /// <summary> </summary>
914                 /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>
915                 public IDirectedCollectionValue<T> this[int start, int end]
916                 { get { return new GuardedDirectedCollectionValue<T>(indexedsorted[start, end]); } }
917
918
919                 /// <summary>
920                 /// Find the (first) index of an item in the wrapped collection
921                 /// </summary>
922                 /// <param name="item"></param>
923                 /// <returns></returns>
924                 public int IndexOf(T item) { return indexedsorted.IndexOf(item); }
925
926
927                 /// <summary>
928                 /// Find the last index of an item in the wrapped collection
929                 /// </summary>
930                 /// <param name="item"></param>
931                 /// <returns></returns>
932                 public int LastIndexOf(T item) { return indexedsorted.LastIndexOf(item); }
933
934
935                 /// <summary>
936                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
937                 /// </summary>
938                 /// <param name="i"></param>
939                 /// <returns></returns>
940                 public T RemoveAt(int i)
941                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
942
943
944                 /// <summary>
945                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
946                 /// </summary>
947                 /// <param name="start"></param>
948                 /// <param name="count"></param>
949                 public void RemoveInterval(int start, int count)
950                 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
951
952                 #endregion
953
954                 #region ISequenced<T> Members
955
956                 int ISequenced<T>.GetHashCode()
957                 { return ((ISequenced<T>)indexedsorted).GetHashCode(); }
958
959
960                 bool ISequenced<T>.Equals(ISequenced<T> that)
961                 { return ((ISequenced<T>)indexedsorted).Equals(that); }
962
963                 #endregion
964
965                 #region IEditableCollection<T> Members
966
967                 int ICollection<T>.GetHashCode()
968                 { return ((ICollection<T>)indexedsorted).GetHashCode(); }
969
970
971                 bool ICollection<T>.Equals(ICollection<T> that)
972                 { return ((ICollection<T>)indexedsorted).Equals(that); }
973
974                 #endregion
975
976                 #region IDirectedEnumerable<T> Members
977
978                 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
979                 { return Backwards(); }
980
981                 #endregion
982         }
983
984
985
986         /// <summary>
987         /// A read-only wrapper for a generic list collection
988         /// <p>Suitable as a wrapper for LinkedList, HashedLinkedList, ArrayList and HashedArray.
989         /// <see cref="T:C5.LinkedList!1"/>, 
990         /// <see cref="T:C5.HashedLinkedList!1"/>, 
991         /// <see cref="T:C5.ArrayList!1"/> or
992         /// <see cref="T:C5.HashedArray!1"/>.
993         /// </p>
994         /// </summary>
995         public class GuardedList<T>: GuardedSequenced<T>, IList<T>
996         {
997                 #region Fields
998
999                 IList<T> list;
1000
1001                 #endregion
1002
1003                 #region Constructor
1004
1005                 /// <summary>
1006                 /// Wrap a list in a read-only wrapper
1007                 /// </summary>
1008                 /// <param name="list">The list</param>
1009                 public GuardedList(IList<T> list) : base (list) { this.list = list; }
1010
1011                 #endregion
1012
1013                 #region IList<T> Members
1014
1015                 /// <summary>
1016                 /// 
1017                 /// </summary>
1018                 /// <value>The first item of the wrapped list</value>
1019                 public T First { get { return list.First; } }
1020
1021
1022                 /// <summary>
1023                 /// 
1024                 /// </summary>
1025                 /// <value>The last item of the wrapped list</value>
1026                 public T Last { get { return list.Last; } }
1027
1028
1029                 /// <summary>
1030                 /// <exception cref="InvalidOperationException"/> if used as setter
1031                 /// </summary>
1032                 /// <value>True if wrapped list has FIFO semantics for the Add(T item) and Remove() methods</value>
1033                 public bool FIFO
1034                 {
1035                         get { return list.FIFO; }
1036                         set { throw new InvalidOperationException("List is read only"); }
1037                 }
1038
1039
1040                 /// <summary>
1041                 /// <exception cref="InvalidOperationException"/> if used as setter
1042                 /// </summary>
1043                 /// <value>The i'th item of the wrapped list</value>
1044                 public T this[int i]
1045                 {
1046                         get { return list[i]; }
1047                         set { throw new InvalidOperationException("List is read only"); }
1048                 }
1049
1050
1051                 /// <summary>
1052                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1053                 /// </summary>
1054                 /// <param name="i"></param>
1055                 /// <param name="item"></param>
1056                 public void Insert(int i, T item)
1057                 { throw new InvalidOperationException("List is read only"); }
1058
1059
1060                 /// <summary>
1061                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1062                 /// </summary>
1063                 /// <param name="item"></param>
1064                 public void InsertFirst(T item)
1065                 { throw new InvalidOperationException("List is read only"); }
1066
1067                 /// <summary>
1068                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1069                 /// </summary>
1070                 /// <param name="item"></param>
1071                 public void InsertLast(T item)
1072                 { throw new InvalidOperationException("List is read only"); }
1073
1074                 /// <summary>
1075                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1076                 /// </summary>
1077                 /// <param name="item"></param>
1078                 /// <param name="target"></param>
1079                 public void InsertBefore(T item, T target)
1080                 { throw new InvalidOperationException("List is read only"); }
1081
1082
1083                 /// <summary>
1084                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1085                 /// </summary>
1086                 /// <param name="item"></param>
1087                 /// <param name="target"></param>
1088                 public void InsertAfter(T item, T target)
1089                 { throw new InvalidOperationException("List is read only"); }
1090
1091
1092                 /// <summary>
1093                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1094                 /// </summary>
1095                 /// <param name="i"></param>
1096                 /// <param name="items"></param>
1097                 public void InsertAll(int i, MSG.IEnumerable<T> items)
1098                 { throw new InvalidOperationException("List is read only"); }
1099
1100
1101                 /// <summary>
1102                 /// Perform FindAll on the wrapped list. The result is <b>not</b> necessarily read-only.
1103                 /// </summary>
1104                 /// <param name="filter">The filter to use</param>
1105                 /// <returns></returns>
1106                 public IList<T> FindAll(Filter<T> filter) { return list.FindAll(filter); }
1107
1108
1109                 /// <summary>
1110                 /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
1111                 /// </summary>
1112         /// <typeparam name="V">The type of items of the new list</typeparam>
1113         /// <param name="mapper">The mapper to use.</param>
1114         /// <returns>The mapped list</returns>
1115         public IList<V> Map<V>(Mapper<T, V> mapper) { return list.Map<V>(mapper); }
1116
1117         /// <summary>
1118         /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
1119         /// </summary>
1120         /// <typeparam name="V">The type of items of the new list</typeparam>
1121         /// <param name="mapper">The delegate defining the map.</param>
1122         /// <param name="hasher">The hasher to use for the new list</param>
1123         /// <returns>The new list.</returns>
1124         public IList<V> Map<V>(Mapper<T, V> mapper, IHasher<V> hasher) { return list.Map<V>(mapper, hasher); }
1125
1126         /// <summary>
1127         /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1128                 /// </summary>
1129                 /// <returns></returns>
1130                 public T Remove() { throw new InvalidOperationException("List is read only"); }
1131
1132
1133                 /// <summary>
1134                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1135                 /// </summary>
1136                 /// <returns></returns>
1137                 public T RemoveFirst() { throw new InvalidOperationException("List is read only"); }
1138
1139
1140                 /// <summary>
1141                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1142                 /// </summary>
1143                 /// <returns></returns>
1144                 public T RemoveLast() { throw new InvalidOperationException("List is read only"); }
1145
1146
1147                 /// <summary>
1148                 /// Create the indicated view on the wrapped list and wrap it read-only.
1149                 /// </summary>
1150                 /// <param name="start"></param>
1151                 /// <param name="count"></param>
1152                 /// <returns></returns>
1153                 public IList<T> View(int start, int count)
1154                 {
1155                         return new GuardedList<T>(list.View(start, count));
1156                 }
1157
1158
1159                 //TODO: This is wrong!
1160                 /// <summary>
1161                 /// (This is wrong functionality)
1162                 /// </summary>
1163         /// <value>The wrapped underlying list of the wrapped view </value>
1164         public IList<T> Underlying { get { return new GuardedList<T>(list.Underlying); } }
1165
1166
1167         /// <summary>
1168                 /// 
1169                 /// </summary>
1170                 /// <value>The offset of the wrapped list as a view.</value>
1171                 public int Offset { get { return list.Offset; } }
1172
1173
1174                 /// <summary>
1175                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1176                 /// </summary>
1177                 /// <param name="offset"></param>
1178                 public void Slide(int offset) { throw new InvalidOperationException("List is read only"); }
1179
1180
1181                 /// <summary>
1182                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1183                 /// </summary>
1184                 /// <param name="offset"></param>
1185                 /// <param name="size"></param>
1186                 public void Slide(int offset, int size) { throw new InvalidOperationException("List is read only"); }
1187
1188
1189                 /// <summary>
1190                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1191                 /// </summary>
1192                 public void Reverse() { throw new InvalidOperationException("List is read only"); }
1193
1194
1195                 /// <summary>
1196                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1197                 /// </summary>
1198                 /// <param name="start"></param>
1199                 /// <param name="count"></param>
1200                 public void Reverse(int start, int count)
1201                 { throw new InvalidOperationException("List is read only"); }
1202
1203
1204                 /// <summary>
1205                 /// Check if wrapped list is sorted
1206                 /// </summary>
1207                 /// <param name="c">The sorting order to use</param>
1208                 /// <returns>True if sorted</returns>
1209                 public bool IsSorted(IComparer<T> c) { return list.IsSorted(c); }
1210
1211
1212                 /// <summary>
1213                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1214                 /// </summary>
1215                 /// <param name="c"></param>
1216                 public void Sort(IComparer<T> c)
1217                 { throw new InvalidOperationException("List is read only"); }
1218
1219
1220                 /// <summary>
1221                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1222                 /// </summary>
1223                 public void Shuffle()
1224                 { throw new InvalidOperationException("List is read only"); }
1225
1226
1227                 /// <summary>
1228                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1229                 /// </summary>
1230                 /// <param name="rnd"></param>
1231                 public void Shuffle(Random rnd)
1232                 { throw new InvalidOperationException("List is read only"); }
1233
1234                 #endregion
1235
1236                 #region IIndexed<T> Members
1237
1238                 /// <summary> </summary>
1239                 /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>
1240                 public IDirectedCollectionValue<T> this[int start, int end]
1241                 { get { return new GuardedDirectedCollectionValue<T>(list[start, end]); } }
1242
1243
1244                 /// <summary>
1245                 /// Find the (first) index of an item in the wrapped collection
1246                 /// </summary>
1247                 /// <param name="item"></param>
1248                 /// <returns></returns>
1249                 public int IndexOf(T item) { return list.IndexOf(item); }
1250
1251
1252                 /// <summary>
1253                 /// Find the last index of an item in the wrapped collection
1254                 /// </summary>
1255                 /// <param name="item"></param>
1256                 /// <returns></returns>
1257                 public int LastIndexOf(T item) { return list.LastIndexOf(item); }
1258
1259
1260                 /// <summary>
1261                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1262                 /// </summary>
1263                 /// <param name="i"></param>
1264                 /// <returns></returns>
1265                 public T RemoveAt(int i)
1266                 { throw new InvalidOperationException("List is read only"); }
1267
1268
1269                 /// <summary>
1270                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1271                 /// </summary>
1272                 /// <param name="start"></param>
1273                 /// <param name="count"></param>
1274                 public void RemoveInterval(int start, int count)
1275                 { throw new InvalidOperationException("List is read only"); }
1276
1277                 #endregion
1278
1279                 #region ISequenced<T> Members
1280
1281                 int ISequenced<T>.GetHashCode()
1282                 { return ((ISequenced<T>)list).GetHashCode(); }
1283
1284
1285                 bool ISequenced<T>.Equals(ISequenced<T> that)
1286                 { return ((ISequenced<T>)list).Equals(that); }
1287
1288                 #endregion
1289
1290                 #region IEditableCollection<T> Members
1291
1292                 int ICollection<T>.GetHashCode()
1293                 { return ((ICollection<T>)list).GetHashCode(); }
1294
1295
1296                 bool ICollection<T>.Equals(ICollection<T> that)
1297                 { return ((ICollection<T>)list).Equals(that); }
1298
1299                 #endregion
1300
1301                 #region IDirectedEnumerable<T> Members
1302
1303                 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
1304                 { return Backwards(); }
1305
1306                 #endregion
1307
1308         #region IStack<T> Members
1309
1310
1311         /// <summary>
1312         /// 
1313         /// </summary>
1314         /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1315         /// <returns>-</returns>
1316         public void Push(T item)
1317         { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
1318
1319         /// <summary>
1320         /// 
1321         /// </summary>
1322         /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1323         /// <returns>-</returns>
1324         public T Pop()
1325         { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
1326
1327                 #endregion
1328
1329         #region IQueue<T> Members
1330
1331         /// <summary>
1332         /// 
1333         /// </summary>
1334         /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1335         /// <returns>-</returns>
1336         public void EnQueue(T item)
1337         { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
1338
1339         /// <summary>
1340         /// 
1341         /// </summary>
1342         /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1343         /// <returns>-</returns>
1344         public T DeQueue()
1345         { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
1346
1347                 #endregion
1348
1349     }
1350
1351
1352
1353         /// <summary>
1354         /// A read-only wrapper for a dictionary.
1355         ///
1356         /// <p>Suitable for wrapping a HashDictionary. <see cref="T:C5.HashDictionary!2"/></p>
1357         /// </summary>
1358         public class GuardedDictionary<K,V>: GuardedEnumerable<KeyValuePair<K,V>>, IDictionary<K,V>
1359         {
1360                 #region Fields
1361
1362                 IDictionary<K,V> dict;
1363
1364                 #endregion
1365
1366                 #region Constructor
1367
1368                 /// <summary>
1369                 /// Wrap a dictionary in a read-only wrapper
1370                 /// </summary>
1371                 /// <param name="dict">the dictionary</param>
1372                 public GuardedDictionary(IDictionary<K,V> dict) : base(dict) { this.dict = dict; }
1373
1374                 #endregion
1375
1376                 #region IDictionary<K,V> Members
1377
1378                 /// <summary>
1379                 /// <exception cref="InvalidOperationException"/> since this is a
1380                 /// read-only wrappper if used as a setter
1381                 /// </summary>
1382                 /// <value>Get the value corresponding to a key in the wrapped dictionary</value>
1383                 public V this[K key]
1384                 {
1385                         get { return dict[key]; }
1386                         set { throw new InvalidOperationException("Dictionary is read only"); }
1387                 }
1388
1389
1390                 /// <summary> </summary>
1391                 /// <value>The size of the wrapped dictionary</value>
1392                 public int Count { get { return dict.Count; } }
1393
1394
1395                 /// <summary>
1396                 /// (This is a read-only wrapper)
1397                 /// </summary>
1398                 /// <value>True</value>
1399                 public bool IsReadOnly { get { return true; } }
1400
1401
1402                 /// <summary> </summary>
1403                 /// <value>The sync root of the wrapped dictionary</value>
1404                 public object SyncRoot { get { return dict.SyncRoot; } }
1405
1406
1407                 //TODO: guard with a read-only wrapper? Probably so!
1408                 /// <summary> </summary>
1409                 /// <value>The collection of keys of the wrapped dictionary</value>
1410                 public ICollectionValue<K> Keys
1411                 { get { return dict.Keys; } }
1412
1413
1414                 /// <summary> </summary>
1415                 /// <value>The collection of values of the wrapped dictionary</value>
1416                 public ICollectionValue<V> Values { get { return dict.Values; } }
1417
1418
1419                 /// <summary>
1420                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1421                 /// </summary>
1422                 /// <param name="key"></param>
1423                 /// <param name="val"></param>
1424                 public void Add(K key, V val)
1425                 { throw new InvalidOperationException("Dictionary is read only"); }
1426
1427
1428                 /// <summary>
1429                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1430                 /// </summary>
1431                 /// <param name="key"></param>
1432                 /// <returns></returns>
1433                 public bool Remove(K key)
1434                 { throw new InvalidOperationException("Dictionary is read only"); }
1435
1436
1437                 /// <summary>
1438                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1439                 /// </summary>
1440                 /// <param name="key"></param>
1441                 /// <param name="val"></param>
1442                 /// <returns></returns>
1443                 public bool Remove(K key, out V val)
1444                 { throw new InvalidOperationException("Dictionary is read only"); }
1445
1446
1447                 /// <summary>
1448                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1449                 /// </summary>
1450                 public void Clear()
1451                 { throw new InvalidOperationException("Dictionary is read only"); }
1452
1453
1454                 /// <summary>
1455                 /// Check if the wrapped dictionary contains a specific key
1456                 /// </summary>
1457                 /// <param name="key">The key</param>
1458                 /// <returns>True if it does</returns>
1459                 public bool Contains(K key) { return dict.Contains(key); }
1460
1461
1462                 /// <summary>
1463                 /// Search for a key in the wrapped dictionary, reporting the value if found
1464                 /// </summary>
1465                 /// <param name="key">The key</param>
1466                 /// <param name="val">On exit: the value if found</param>
1467                 /// <returns>True if found</returns>
1468                 public bool Find(K key, out V val) { return dict.Find(key, out val); }
1469
1470
1471                 /// <summary>
1472                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1473                 /// </summary>
1474                 /// <param name="key"></param>
1475                 /// <param name="val"></param>
1476                 /// <returns></returns>
1477                 public bool Update(K key, V val)
1478                 { throw new InvalidOperationException("Dictionary is read only"); }
1479
1480
1481                 /// <summary>
1482                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1483                 /// </summary>
1484                 /// <param name="key"></param>
1485                 /// <param name="val"></param>
1486                 /// <returns></returns>
1487                 public bool FindOrAdd(K key, ref V val)
1488                 { throw new InvalidOperationException("Dictionary is read only"); }
1489
1490
1491                 /// <summary>
1492                 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1493                 /// </summary>
1494                 /// <param name="key"></param>
1495                 /// <param name="val"></param>
1496                 /// <returns></returns>
1497                 public bool UpdateOrAdd(K key, V val)
1498                 { throw new InvalidOperationException("Dictionary is read only"); }
1499
1500
1501                 /// <summary>
1502                 /// Check the internal consistency of the wrapped dictionary
1503                 /// </summary>
1504                 /// <returns>True if check passed</returns>
1505                 public bool Check() { return dict.Check(); }
1506
1507                 #endregion
1508         }
1509
1510
1511
1512         /// <summary>
1513         /// A read-only wrapper for a sorted dictionary.
1514         ///
1515         /// <p>Suitable for wrapping a Dictionary. <see cref="T:C5.Dictionary!2"/></p>
1516         /// </summary>
1517         public class GuardedSortedDictionary<K,V>: GuardedDictionary<K,V>, ISortedDictionary<K,V>
1518         {
1519                 #region Fields
1520
1521                 ISortedDictionary<K,V> sorteddict;
1522
1523                 #endregion
1524
1525                 #region Constructor
1526
1527                 /// <summary>
1528                 /// Wrap a sorted dictionary in a read-only wrapper
1529                 /// </summary>
1530                 /// <param name="sorteddict">the dictionary</param>
1531                 public GuardedSortedDictionary(ISortedDictionary<K,V> sorteddict) :base(sorteddict)
1532                 { this.sorteddict = sorteddict; }
1533
1534                 #endregion
1535
1536                 #region ISortedDictionary<K,V> Members
1537
1538                 /// <summary>
1539                 /// Get the entry in the wrapped dictionary whose key is the
1540                 /// predecessor of a specified key.
1541                 /// </summary>
1542                 /// <param name="key">The key</param>
1543                 /// <returns>The entry</returns>
1544                 public KeyValuePair<K,V> Predecessor(K key)
1545                 { return sorteddict.Predecessor(key); }
1546
1547
1548                 /// <summary>
1549                 /// Get the entry in the wrapped dictionary whose key is the
1550                 /// successor of a specified key.
1551                 /// </summary>
1552                 /// <param name="key">The key</param>
1553                 /// <returns>The entry</returns>
1554                 public KeyValuePair<K,V> Successor(K key)
1555                 { return sorteddict.Successor(key); }
1556
1557
1558                 /// <summary>
1559                 /// Get the entry in the wrapped dictionary whose key is the
1560                 /// weak predecessor of a specified key.
1561                 /// </summary>
1562                 /// <param name="key">The key</param>
1563                 /// <returns>The entry</returns>
1564                 public KeyValuePair<K,V> WeakPredecessor(K key)
1565                 { return sorteddict.WeakPredecessor(key); }
1566
1567
1568                 /// <summary>
1569                 /// Get the entry in the wrapped dictionary whose key is the
1570                 /// weak successor of a specified key.
1571                 /// </summary>
1572                 /// <param name="key">The key</param>
1573                 /// <returns>The entry</returns>
1574                 public KeyValuePair<K,V> WeakSuccessor(K key)
1575                 { return sorteddict.WeakSuccessor(key); }
1576
1577                 #endregion
1578         }
1579
1580 }
1581 #endif