Merge pull request #3025 from kumpera/mono_raise_exception_in_threads
[mono.git] / mcs / class / Mono.C5 / C5 / Wrappers.cs
1 /*
2  Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
3  Permission is hereby granted, free of charge, to any person obtaining a copy
4  of this software and associated documentation files (the "Software"), to deal
5  in the Software without restriction, including without limitation the rights
6  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7  copies of the Software, and to permit persons to whom the Software is
8  furnished to do so, subject to the following conditions:
9  
10  The above copyright notice and this permission notice shall be included in
11  all copies or substantial portions of the Software.
12  
13  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19  SOFTWARE.
20 */
21
22 using System;
23 using System.Diagnostics;
24 using SCG = System.Collections.Generic;
25 namespace C5
26 {
27   /// <summary>
28   /// A read-only wrapper class for a generic enumerator
29   /// </summary>
30   public class GuardedEnumerator<T> : SCG.IEnumerator<T>
31   {
32     #region Fields
33
34     SCG.IEnumerator<T> enumerator;
35
36     #endregion
37
38     #region Constructor
39
40     /// <summary>
41     /// Create a wrapper around a generic enumerator
42     /// </summary>
43     /// <param name="enumerator">The enumerator to wrap</param>
44     public GuardedEnumerator(SCG.IEnumerator<T> enumerator)
45     { this.enumerator = enumerator; }
46
47     #endregion
48
49     #region IEnumerator<T> Members
50
51     /// <summary>
52     /// Move wrapped enumerator to next item, or the first item if
53     /// this is the first call to MoveNext. 
54     /// </summary>
55     /// <returns>True if enumerator is valid now</returns>
56     public bool MoveNext() { return enumerator.MoveNext(); }
57
58
59     /// <summary>
60     /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
61     /// </summary>
62     /// <value>The current item of the wrapped enumerator.</value>
63     public T Current { get { return enumerator.Current; } }
64
65     #endregion
66
67     #region IDisposable Members
68
69     //TODO: consider possible danger of calling through to Dispose. 
70     /// <summary>
71     /// Dispose wrapped enumerator.
72     /// </summary>
73     public void Dispose() { enumerator.Dispose(); }
74
75     #endregion
76
77
78     #region IEnumerator Members
79
80     object System.Collections.IEnumerator.Current
81     {
82       get { return enumerator.Current; }
83     }
84
85     void System.Collections.IEnumerator.Reset()
86     {
87       enumerator.Reset();
88     }
89
90     #endregion
91   }
92
93
94
95   /// <summary>
96   /// A read-only wrapper class for a generic enumerable
97   ///
98   /// <i>This is mainly interesting as a base of other guard classes</i>
99   /// </summary>
100   public class GuardedEnumerable<T> : SCG.IEnumerable<T>
101   {
102     #region Fields
103
104     SCG.IEnumerable<T> enumerable;
105
106     #endregion
107
108     #region Constructor
109
110     /// <summary>
111     /// Wrap an enumerable in a read-only wrapper
112     /// </summary>
113     /// <param name="enumerable">The enumerable to wrap</param>
114     public GuardedEnumerable(SCG.IEnumerable<T> enumerable)
115     { this.enumerable = enumerable; }
116
117     #endregion
118
119     #region SCG.IEnumerable<T> Members
120
121     /// <summary>
122     /// Get an enumerator from the wrapped enumerable
123     /// </summary>
124     /// <returns>The enumerator (itself wrapped)</returns>
125     public SCG.IEnumerator<T> GetEnumerator()
126     { return new GuardedEnumerator<T>(enumerable.GetEnumerator()); }
127
128     #endregion
129
130     #region IEnumerable Members
131
132     System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
133     {
134       return GetEnumerator();
135     }
136
137     #endregion
138
139   }
140
141
142
143   /// <summary>
144   /// A read-only wrapper for a generic directed enumerable
145   ///
146   /// <i>This is mainly interesting as a base of other guard classes</i>
147   /// </summary>
148   public class GuardedDirectedEnumerable<T> : GuardedEnumerable<T>, IDirectedEnumerable<T>
149   {
150     #region Fields
151
152     IDirectedEnumerable<T> directedenumerable;
153
154     #endregion
155
156     #region Constructor
157
158     /// <summary>
159     /// Wrap a directed enumerable in a read-only wrapper
160     /// </summary>
161     /// <param name="directedenumerable">the collection to wrap</param>
162     public GuardedDirectedEnumerable(IDirectedEnumerable<T> directedenumerable)
163       : base(directedenumerable)
164     { this.directedenumerable = directedenumerable; }
165
166     #endregion
167
168     #region IDirectedEnumerable<T> Members
169
170     /// <summary>
171     /// Get a enumerable that enumerates the wrapped collection in the opposite direction
172     /// </summary>
173     /// <returns>The mirrored enumerable</returns>
174     public IDirectedEnumerable<T> Backwards()
175     { return new GuardedDirectedEnumerable<T>(directedenumerable.Backwards()); }
176
177
178     /// <summary>
179     /// <code>Forwards</code> if same, else <code>Backwards</code>
180     /// </summary>
181     /// <value>The enumeration direction relative to the original collection.</value>
182     public EnumerationDirection Direction
183     { get { return directedenumerable.Direction; } }
184
185     #endregion
186   }
187
188
189
190   /// <summary>
191   /// A read-only wrapper for an ICollectionValue&lt;T&gt;
192   ///
193   /// <i>This is mainly interesting as a base of other guard classes</i>
194   /// </summary>
195   public class GuardedCollectionValue<T> : GuardedEnumerable<T>, ICollectionValue<T>
196   {
197     #region Events
198     /// <summary>
199     /// The ListenableEvents value of the wrapped collection
200     /// </summary>
201     /// <value></value>
202     public virtual EventTypeEnum ListenableEvents { get { return collectionvalue.ListenableEvents; } }
203
204     /// <summary>
205     /// The ActiveEvents value of the wrapped collection
206     /// </summary>
207     /// <value></value>
208     public virtual EventTypeEnum ActiveEvents { get { return collectionvalue.ActiveEvents; } }
209
210     ProxyEventBlock<T> eventBlock;
211     /// <summary>
212     /// The change event. Will be raised for every change operation on the collection.
213     /// </summary>
214     public event CollectionChangedHandler<T> CollectionChanged
215     {
216       add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).CollectionChanged += value; }
217       remove { if (eventBlock != null) eventBlock.CollectionChanged -= value; }
218     }
219
220     /// <summary>
221     /// The change event. Will be raised for every change operation on the collection.
222     /// </summary>
223     public event CollectionClearedHandler<T> CollectionCleared
224     {
225       add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).CollectionCleared += value; }
226       remove { if (eventBlock != null) eventBlock.CollectionCleared -= value; }
227     }
228
229     /// <summary>
230     /// The item added  event. Will be raised for every individual addition to the collection.
231     /// </summary>
232     public event ItemsAddedHandler<T> ItemsAdded
233     {
234       add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemsAdded += value; }
235       remove { if (eventBlock != null) eventBlock.ItemsAdded -= value; }
236     }
237
238     /// <summary>
239     /// The item added  event. Will be raised for every individual addition to the collection.
240     /// </summary>
241     public event ItemInsertedHandler<T> ItemInserted
242     {
243       add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemInserted += value; }
244       remove { if (eventBlock != null) eventBlock.ItemInserted -= value; }
245     }
246
247     /// <summary>
248     /// The item removed event. Will be raised for every individual removal from the collection.
249     /// </summary>
250     public event ItemsRemovedHandler<T> ItemsRemoved
251     {
252       add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemsRemoved += value; }
253       remove { if (eventBlock != null) eventBlock.ItemsRemoved -= value; }
254     }
255
256     /// <summary>
257     /// The item removed event. Will be raised for every individual removal from the collection.
258     /// </summary>
259     public event ItemRemovedAtHandler<T> ItemRemovedAt
260     {
261       add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemRemovedAt += value; }
262       remove { if (eventBlock != null) eventBlock.ItemRemovedAt -= value; }
263     }
264     #endregion
265
266     #region Fields
267
268     ICollectionValue<T> collectionvalue;
269
270     #endregion
271
272     #region Constructor
273
274     /// <summary>
275     /// Wrap a ICollectionValue&lt;T&gt; in a read-only wrapper
276     /// </summary>
277     /// <param name="collectionvalue">the collection to wrap</param>
278     public GuardedCollectionValue(ICollectionValue<T> collectionvalue)
279       : base(collectionvalue)
280     { this.collectionvalue = collectionvalue; }
281
282     #endregion
283
284     #region ICollection<T> Members
285
286     /// <summary>
287     /// Get the size of the wrapped collection
288     /// </summary>
289     /// <value>The size</value>
290     public virtual bool IsEmpty { get { return collectionvalue.IsEmpty; } }
291
292     /// <summary>
293     /// Get the size of the wrapped collection
294     /// </summary>
295     /// <value>The size</value>
296     public virtual int Count { get { return collectionvalue.Count; } }
297
298     /// <summary>
299     /// The value is symbolic indicating the type of asymptotic complexity
300     /// in terms of the size of this collection (worst-case or amortized as
301     /// relevant).
302     /// </summary>
303     /// <value>A characterization of the speed of the 
304     /// <code>Count</code> property in this collection.</value>
305     public virtual Speed CountSpeed { get { return collectionvalue.CountSpeed; } }
306
307     /// <summary>
308     /// Copy the items of the wrapped collection to an array
309     /// </summary>
310     /// <param name="a">The array</param>
311     /// <param name="i">Starting offset</param>
312     public virtual void CopyTo(T[] a, int i) { collectionvalue.CopyTo(a, i); }
313
314     /// <summary>
315     /// Create an array from the items of the wrapped collection
316     /// </summary>
317     /// <returns>The array</returns>
318     public virtual T[] ToArray() { return collectionvalue.ToArray(); }
319
320     /// <summary>
321     /// Apply a delegate to all items of the wrapped enumerable.
322     /// </summary>
323     /// <param name="a">The delegate to apply</param>
324     //TODO: change this to throw an exception?
325     public virtual void Apply(Act<T> a) { collectionvalue.Apply(a); }
326
327
328     /// <summary>
329     /// Check if there exists an item  that satisfies a
330     /// specific predicate in the wrapped enumerable.
331     /// </summary>
332     /// <param name="filter">A filter delegate 
333     /// (<see cref="T:C5.Filter`1"/>) defining the predicate</param>
334     /// <returns>True is such an item exists</returns>
335     public virtual bool Exists(Fun<T, bool> filter) { return collectionvalue.Exists(filter); }
336
337     /// <summary>
338     /// 
339     /// </summary>
340     /// <param name="filter"></param>
341     /// <param name="item"></param>
342     /// <returns></returns>
343     public virtual bool Find(Fun<T, bool> filter, out T item) { return collectionvalue.Find(filter, out item); }
344
345     /// <summary>
346     /// Check if all items in the wrapped enumerable satisfies a specific predicate.
347     /// </summary>
348     /// <param name="filter">A filter delegate 
349     /// (<see cref="T:C5.Filter`1"/>) defining the predicate</param>
350     /// <returns>True if all items satisfies the predicate</returns>
351     public virtual bool All(Fun<T, bool> filter) { return collectionvalue.All(filter); }
352
353     /// <summary>
354     /// Create an enumerable, enumerating the items of this collection that satisfies 
355     /// a certain condition.
356     /// </summary>
357     /// <param name="filter">The T->bool filter delegate defining the condition</param>
358     /// <returns>The filtered enumerable</returns>
359     public virtual SCG.IEnumerable<T> Filter(Fun<T, bool> filter) { return collectionvalue.Filter(filter); }
360
361     /// <summary>
362     /// Choose some item of this collection. 
363     /// </summary>
364     /// <exception cref="NoSuchItemException">if collection is empty.</exception>
365     /// <returns></returns>
366     public virtual T Choose() { return collectionvalue.Choose(); }
367
368     #endregion
369
370     #region IShowable Members
371
372     /// <summary>
373     /// 
374     /// </summary>
375     /// <param name="stringbuilder"></param>
376     /// <param name="formatProvider"></param>
377     /// <param name="rest"></param>
378     /// <returns></returns>
379     public bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
380     {
381       return collectionvalue.Show(stringbuilder, ref rest, formatProvider);
382     }
383     #endregion
384
385     #region IFormattable Members
386
387     /// <summary>
388     /// 
389     /// </summary>
390     /// <param name="format"></param>
391     /// <param name="formatProvider"></param>
392     /// <returns></returns>
393     public string ToString(string format, IFormatProvider formatProvider)
394     {
395       return collectionvalue.ToString(format, formatProvider);
396     }
397
398     #endregion
399   }
400
401
402
403   /// <summary>
404   /// A read-only wrapper for a directed collection
405   ///
406   /// <i>This is mainly interesting as a base of other guard classes</i>
407   /// </summary>
408   public class GuardedDirectedCollectionValue<T> : GuardedCollectionValue<T>, IDirectedCollectionValue<T>
409   {
410     #region Fields
411
412     IDirectedCollectionValue<T> directedcollection;
413
414     #endregion
415
416     #region Constructor
417
418     /// <summary>
419     /// Wrap a directed collection in a read-only wrapper
420     /// </summary>
421     /// <param name="directedcollection">the collection to wrap</param>
422     public GuardedDirectedCollectionValue(IDirectedCollectionValue<T> directedcollection)
423       :
424       base(directedcollection)
425     { this.directedcollection = directedcollection; }
426
427     #endregion
428
429     #region IDirectedCollection<T> Members
430
431     /// <summary>
432     /// Get a collection that enumerates the wrapped collection in the opposite direction
433     /// </summary>
434     /// <returns>The mirrored collection</returns>
435     public virtual IDirectedCollectionValue<T> Backwards()
436     { return new GuardedDirectedCollectionValue<T>(directedcollection.Backwards()); }
437
438     /// <summary>
439     /// 
440     /// </summary>
441     /// <param name="predicate"></param>
442     /// <param name="item"></param>
443     /// <returns></returns>
444     public virtual bool FindLast(Fun<T, bool> predicate, out T item) { return directedcollection.FindLast(predicate, out item); }
445
446     #endregion
447
448     #region IDirectedEnumerable<T> Members
449
450     IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
451     { return Backwards(); }
452
453
454     /// <summary>
455     /// <code>Forwards</code> if same, else <code>Backwards</code>
456     /// </summary>
457     /// <value>The enumeration direction relative to the original collection.</value>
458     public EnumerationDirection Direction
459     { get { return directedcollection.Direction; } }
460
461     #endregion
462   }
463
464
465
466   /// <summary>
467   /// A read-only wrapper for an <see cref="T:C5.ICollection`1"/>,
468   /// <para>
469   /// <i>Suitable for wrapping hash tables, <see cref="T:C5.HashSet`1"/>
470   /// and <see cref="T:C5.HashBag`1"/>  </i></para>
471   /// </summary>
472   public class GuardedCollection<T> : GuardedCollectionValue<T>, ICollection<T>
473   {
474     #region Fields
475
476     ICollection<T> collection;
477
478     #endregion
479
480     #region Constructor
481
482     /// <summary>
483     /// Wrap an ICollection&lt;T&gt; in a read-only wrapper
484     /// </summary>
485     /// <param name="collection">the collection to wrap</param>
486     public GuardedCollection(ICollection<T> collection)
487       : base(collection)
488     {
489       this.collection = collection;
490     }
491
492     #endregion
493
494     #region ICollection<T> Members
495
496     /// <summary>
497     /// (This is a read-only wrapper)
498     /// </summary>
499     /// <value>True</value>
500     public virtual bool IsReadOnly { get { return true; } }
501
502
503     /// <summary> </summary>
504     /// <value>Speed of wrapped collection</value>
505     public virtual Speed ContainsSpeed { get { return collection.ContainsSpeed; } }
506
507     /// <summary>
508     /// 
509     /// </summary>
510     /// <returns></returns>
511     public virtual int GetUnsequencedHashCode()
512     { return collection.GetUnsequencedHashCode(); }
513
514     /// <summary>
515     /// 
516     /// </summary>
517     /// <param name="that"></param>
518     /// <returns></returns>
519     public virtual bool UnsequencedEquals(ICollection<T> that)
520     { return collection.UnsequencedEquals(that); }
521
522
523     /// <summary>
524     /// Check if an item is in the wrapped collection
525     /// </summary>
526     /// <param name="item">The item</param>
527     /// <returns>True if found</returns>
528     public virtual bool Contains(T item) { return collection.Contains(item); }
529
530
531     /// <summary>
532     /// Count the number of times an item appears in the wrapped collection
533     /// </summary>
534     /// <param name="item">The item</param>
535     /// <returns>The number of copies</returns>
536     public virtual int ContainsCount(T item) { return collection.ContainsCount(item); }
537
538     /// <summary>
539     /// 
540     /// </summary>
541     /// <returns></returns>
542     public virtual ICollectionValue<T> UniqueItems() { return new GuardedCollectionValue<T>(collection.UniqueItems()); }
543
544     /// <summary>
545     /// 
546     /// </summary>
547     /// <returns></returns>
548     public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities() { return new GuardedCollectionValue<KeyValuePair<T, int>>(collection.ItemMultiplicities()); }
549
550     /// <summary>
551     /// Check if all items in the argument is in the wrapped collection
552     /// </summary>
553     /// <param name="items">The items</param>
554     /// <typeparam name="U"></typeparam>
555     /// <returns>True if so</returns>
556     public virtual bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T { return collection.ContainsAll(items); }
557
558     /// <summary> 
559     /// Search for an item in the wrapped collection
560     /// </summary>
561     /// <param name="item">On entry the item to look for, on exit the equivalent item found (if any)</param>
562     /// <returns></returns>
563     public virtual bool Find(ref T item) { return collection.Find(ref item); }
564
565
566     /// <summary>
567     /// </summary>
568     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
569     /// <param name="item"></param>
570     /// <returns></returns>
571     public virtual bool FindOrAdd(ref T item)
572     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
573
574
575     /// <summary>
576     /// </summary>
577     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
578     /// <param name="item"></param>
579     /// <returns></returns>
580     public virtual bool Update(T item)
581     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
582
583
584     /// <summary>
585     /// </summary>
586     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
587     /// <param name="item"></param>
588     /// <param name="olditem"></param>
589     /// <returns></returns>
590     public virtual bool Update(T item, out T olditem)
591     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
592
593
594     /// <summary>
595     /// </summary>
596     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
597     /// <param name="item"></param>
598     /// <returns></returns>
599     public virtual bool UpdateOrAdd(T item)
600     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
601
602
603     /// <summary>
604     /// </summary>
605     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
606     /// <param name="item"></param>
607     /// <param name="olditem"></param>
608     /// <returns></returns>
609     public virtual bool UpdateOrAdd(T item, out T olditem)
610     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
611
612     /// <summary>
613     /// </summary>
614     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
615     /// <param name="item"></param>
616     /// <returns></returns>
617     public virtual bool Remove(T item)
618     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
619
620
621     /// <summary>
622     /// </summary>
623     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
624     /// <param name="item">The value to remove.</param>
625     /// <param name="removeditem">The removed value.</param>
626     /// <returns></returns>
627     public virtual bool Remove(T item, out T removeditem)
628     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
629
630
631     /// <summary>
632     /// </summary>
633     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
634     /// <param name="item"></param>
635     public virtual void RemoveAllCopies(T item)
636     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
637
638
639     /// <summary>
640     /// </summary>
641     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
642     /// <typeparam name="U"></typeparam>
643     /// <param name="items"></param>
644     public virtual void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T
645     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
646
647     /// <summary>
648     /// </summary>
649     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
650     public virtual void Clear()
651     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
652
653
654     /// <summary>
655     /// </summary>
656     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
657     /// <typeparam name="U"></typeparam>
658     /// <param name="items"></param>
659     public virtual void RetainAll<U>(SCG.IEnumerable<U> items) where U : T
660     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
661
662     /// <summary>
663     /// Check  wrapped collection for internal consistency
664     /// </summary>
665     /// <returns>True if check passed</returns>
666     public virtual bool Check() { return collection.Check(); }
667
668     #endregion
669
670     #region IExtensible<T> Members
671
672     /// <summary> </summary>
673     /// <value>False if wrapped collection has set semantics</value>
674     public virtual bool AllowsDuplicates { get { return collection.AllowsDuplicates; } }
675
676     //TODO: the equalityComparer should be guarded
677     /// <summary>
678     /// 
679     /// </summary>
680     /// <value></value>
681     public virtual SCG.IEqualityComparer<T> EqualityComparer { get { return collection.EqualityComparer; } }
682
683     /// <summary>
684     /// By convention this is true for any collection with set semantics.
685     /// </summary>
686     /// <value>True if only one representative of a group of equal items 
687     /// is kept in the collection together with the total count.</value>
688     public virtual bool DuplicatesByCounting { get { return collection.DuplicatesByCounting; } }
689
690
691     /// <summary> </summary>
692     /// <value>True if wrapped collection is empty</value>
693     public override bool IsEmpty { get { return collection.IsEmpty; } }
694
695
696     /// <summary>
697     /// </summary>
698     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
699     /// <param name="item"></param>
700     /// <returns></returns>
701     public virtual bool Add(T item)
702     { throw new ReadOnlyCollectionException(); }
703
704     /// <summary>
705     /// </summary>
706     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
707     /// <param name="item"></param>
708     void SCG.ICollection<T>.Add(T item)
709     { throw new ReadOnlyCollectionException(); }
710
711     /// <summary>
712     /// </summary>
713     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
714     /// <typeparam name="U"></typeparam>
715     /// <param name="items"></param>
716     public virtual void AddAll<U>(SCG.IEnumerable<U> items) where U : T
717     { throw new ReadOnlyCollectionException(); }
718
719     #endregion
720
721     #region ICloneable Members
722
723     /// <summary>
724     /// 
725     /// </summary>
726     /// <returns></returns>
727     public virtual object Clone()
728     {
729       return new GuardedCollection<T>((ICollection<T>)(collection.Clone()));
730     }
731
732     #endregion
733
734   }
735
736
737   /// <summary>
738   /// A read-only wrapper for a sequenced collection
739   ///
740   /// <i>This is mainly interesting as a base of other guard classes</i>
741   /// </summary>
742   public class GuardedSequenced<T> : GuardedCollection<T>, ISequenced<T>
743   {
744     #region Fields
745
746     ISequenced<T> sequenced;
747
748     #endregion
749
750     #region Constructor
751
752     /// <summary>
753     /// Wrap a sequenced collection in a read-only wrapper
754     /// </summary>
755     /// <param name="sorted"></param>
756     public GuardedSequenced(ISequenced<T> sorted) : base(sorted) { this.sequenced = sorted; }
757
758     #endregion
759
760     /// <summary>
761     /// Check if there exists an item  that satisfies a
762     /// specific predicate in this collection and return the index of the first one.
763     /// </summary>
764     /// <param name="predicate">A delegate 
765     /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
766     /// <returns>the index, if found, a negative value else</returns>
767     public int FindIndex(Fun<T, bool> predicate)
768     {
769       IIndexed<T> indexed = sequenced as IIndexed<T>;
770       if (indexed != null)
771         return indexed.FindIndex(predicate);
772       int index = 0;
773       foreach (T item in this)
774       {
775         if (predicate(item))
776           return index;
777         index++;
778       }
779       return -1;
780     }
781
782     /// <summary>
783     /// Check if there exists an item  that satisfies a
784     /// specific predicate in this collection and return the index of the last one.
785     /// </summary>
786     /// <param name="predicate">A delegate 
787     /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
788     /// <returns>the index, if found, a negative value else</returns>
789     public int FindLastIndex(Fun<T, bool> predicate)
790     {
791       IIndexed<T> indexed = sequenced as IIndexed<T>;
792       if (indexed != null)
793         return indexed.FindLastIndex(predicate);
794       int index = Count - 1;
795       foreach (T item in Backwards())
796       {
797         if (predicate(item))
798           return index;
799         index--;
800       }
801       return -1;
802     }
803
804
805
806     #region ISequenced<T> Members
807
808     /// <summary>
809     /// 
810     /// </summary>
811     /// <returns></returns>
812     public int GetSequencedHashCode()
813     { return sequenced.GetSequencedHashCode(); }
814
815     /// <summary>
816     /// 
817     /// </summary>
818     /// <param name="that"></param>
819     /// <returns></returns>
820     public bool SequencedEquals(ISequenced<T> that)
821     { return sequenced.SequencedEquals(that); }
822
823     #endregion
824
825     #region IDirectedCollection<T> Members
826
827     /// <summary>
828     /// Get a collection that enumerates the wrapped collection in the opposite direction
829     /// </summary>
830     /// <returns>The mirrored collection</returns>
831     public virtual IDirectedCollectionValue<T> Backwards()
832     { return new GuardedDirectedCollectionValue<T>(sequenced.Backwards()); }
833
834     /// <summary>
835     /// 
836     /// </summary>
837     /// <param name="predicate"></param>
838     /// <param name="item"></param>
839     /// <returns></returns>
840     public virtual bool FindLast(Fun<T, bool> predicate, out T item) { return sequenced.FindLast(predicate, out item); }
841
842     #endregion
843
844     #region IDirectedEnumerable<T> Members
845
846     IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
847     { return Backwards(); }
848
849
850
851     /// <summary>
852     /// <code>Forwards</code> if same, else <code>Backwards</code>
853     /// </summary>
854     /// <value>The enumeration direction relative to the original collection.</value>
855     public EnumerationDirection Direction
856     { get { return EnumerationDirection.Forwards; } }
857
858     #endregion
859
860     #region ICloneable Members
861
862     /// <summary>
863     /// 
864     /// </summary>
865     /// <returns></returns>
866     public override object Clone()
867     {
868       return new GuardedCollection<T>((ISequenced<T>)(sequenced.Clone()));
869     }
870
871     #endregion
872
873   }
874
875
876   /// <summary>
877   /// A read-only wrapper for a sorted collection
878   ///
879   /// <i>This is mainly interesting as a base of other guard classes</i>
880   /// </summary>
881   public class GuardedSorted<T> : GuardedSequenced<T>, ISorted<T>
882   {
883     #region Fields
884
885     ISorted<T> sorted;
886
887     #endregion
888
889     #region Constructor
890
891     /// <summary>
892     /// Wrap a sorted collection in a read-only wrapper
893     /// </summary>
894     /// <param name="sorted"></param>
895     public GuardedSorted(ISorted<T> sorted) : base(sorted) { this.sorted = sorted; }
896
897     #endregion
898
899     #region ISorted<T> Members
900
901     /// <summary>
902     /// Find the strict predecessor of item in the guarded sorted collection,
903     /// that is, the greatest item in the collection smaller than the item.
904     /// </summary>
905     /// <param name="item">The item to find the predecessor for.</param>
906     /// <param name="res">The predecessor, if any; otherwise the default value for T.</param>
907     /// <returns>True if item has a predecessor; otherwise false.</returns>
908     public bool TryPredecessor(T item, out T res) { return sorted.TryPredecessor(item, out res); }
909
910
911     /// <summary>
912     /// Find the strict successor of item in the guarded sorted collection,
913     /// that is, the least item in the collection greater than the supplied value.
914     /// </summary>
915     /// <param name="item">The item to find the successor for.</param>
916     /// <param name="res">The successor, if any; otherwise the default value for T.</param>
917     /// <returns>True if item has a successor; otherwise false.</returns>
918     public bool TrySuccessor(T item, out T res) { return sorted.TrySuccessor(item, out res); }
919
920
921     /// <summary>
922     /// Find the weak predecessor of item in the guarded sorted collection,
923     /// that is, the greatest item in the collection smaller than or equal to the item.
924     /// </summary>
925     /// <param name="item">The item to find the weak predecessor for.</param>
926     /// <param name="res">The weak predecessor, if any; otherwise the default value for T.</param>
927     /// <returns>True if item has a weak predecessor; otherwise false.</returns>
928     public bool TryWeakPredecessor(T item, out T res) { return sorted.TryWeakPredecessor(item, out res); }
929
930
931     /// <summary>
932     /// Find the weak successor of item in the sorted collection,
933     /// that is, the least item in the collection greater than or equal to the supplied value.
934     /// </summary>
935     /// <param name="item">The item to find the weak successor for.</param>
936     /// <param name="res">The weak successor, if any; otherwise the default value for T.</param>
937     /// <returns>True if item has a weak successor; otherwise false.</returns>
938     public bool TryWeakSuccessor(T item, out T res) { return sorted.TryWeakSuccessor(item, out res); }
939
940
941     /// <summary>
942     /// Find the predecessor of the item in the wrapped sorted collection
943     /// </summary>
944     /// <exception cref="NoSuchItemException"> if no such element exists </exception>    
945     /// <param name="item">The item</param>
946     /// <returns>The predecessor</returns>
947     public T Predecessor(T item) { return sorted.Predecessor(item); }
948
949
950     /// <summary>
951     /// Find the Successor of the item in the wrapped sorted collection
952     /// </summary>
953     /// <exception cref="NoSuchItemException"> if no such element exists </exception>    
954     /// <param name="item">The item</param>
955     /// <returns>The Successor</returns>
956     public T Successor(T item) { return sorted.Successor(item); }
957
958
959     /// <summary>
960     /// Find the weak predecessor of the item in the wrapped sorted collection
961     /// </summary>
962     /// <exception cref="NoSuchItemException"> if no such element exists </exception>    
963     /// <param name="item">The item</param>
964     /// <returns>The weak predecessor</returns>
965     public T WeakPredecessor(T item) { return sorted.WeakPredecessor(item); }
966
967
968     /// <summary>
969     /// Find the weak Successor of the item in the wrapped sorted collection
970     /// </summary>
971     /// <exception cref="NoSuchItemException"> if no such element exists </exception>    
972     /// <param name="item">The item</param>
973     /// <returns>The weak Successor</returns>
974     public T WeakSuccessor(T item) { return sorted.WeakSuccessor(item); }
975
976
977     /// <summary>
978     /// Run Cut on the wrapped sorted collection
979     /// </summary>
980     /// <param name="c"></param>
981     /// <param name="low"></param>
982     /// <param name="lval"></param>
983     /// <param name="high"></param>
984     /// <param name="hval"></param>
985     /// <returns></returns>
986     public bool Cut(IComparable<T> c, out T low, out bool lval, out T high, out bool hval)
987     { return sorted.Cut(c, out low, out lval, out high, out hval); }
988
989
990     /// <summary>
991     /// Get the specified range from the wrapped collection. 
992     /// (The current implementation erroneously does not wrap the result.)
993     /// </summary>
994     /// <param name="bot"></param>
995     /// <returns></returns>
996     public IDirectedEnumerable<T> RangeFrom(T bot) { return sorted.RangeFrom(bot); }
997
998
999     /// <summary>
1000     /// Get the specified range from the wrapped collection. 
1001     /// (The current implementation erroneously does not wrap the result.)
1002     /// </summary>
1003     /// <param name="bot"></param>
1004     /// <param name="top"></param>
1005     /// <returns></returns>
1006     public IDirectedEnumerable<T> RangeFromTo(T bot, T top)
1007     { return sorted.RangeFromTo(bot, top); }
1008
1009
1010     /// <summary>
1011     /// Get the specified range from the wrapped collection. 
1012     /// (The current implementation erroneously does not wrap the result.)
1013     /// </summary>
1014     /// <param name="top"></param>
1015     /// <returns></returns>
1016     public IDirectedEnumerable<T> RangeTo(T top) { return sorted.RangeTo(top); }
1017
1018
1019     /// <summary>
1020     /// Get the specified range from the wrapped collection. 
1021     /// (The current implementation erroneously does not wrap the result.)
1022     /// </summary>
1023     /// <returns></returns>
1024     public IDirectedCollectionValue<T> RangeAll() { return sorted.RangeAll(); }
1025
1026     /// <summary>
1027     /// </summary>
1028     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1029     /// <param name="items"></param>
1030     /// <typeparam name="U"></typeparam>
1031     public void AddSorted<U>(SCG.IEnumerable<U> items) where U : T
1032     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1033
1034     /// <summary>
1035     /// </summary>
1036     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1037     /// <param name="low"></param>
1038     public void RemoveRangeFrom(T low)
1039     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1040
1041
1042     /// <summary>
1043     /// </summary>
1044     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1045     /// <param name="low"></param>
1046     /// <param name="hi"></param>
1047     public void RemoveRangeFromTo(T low, T hi)
1048     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1049
1050
1051     /// <summary>
1052     /// </summary>
1053     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1054     /// <param name="hi"></param>
1055     public void RemoveRangeTo(T hi)
1056     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1057
1058     #endregion
1059
1060     #region IPriorityQueue<T> Members
1061
1062     /// <summary>
1063     /// Find the minimum of the wrapped collection
1064     /// </summary>
1065     /// <returns>The minimum</returns>
1066     public T FindMin() { return sorted.FindMin(); }
1067
1068
1069     /// <summary>
1070     /// </summary>
1071     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1072     /// <returns></returns>
1073     public T DeleteMin()
1074     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1075
1076
1077     /// <summary>
1078     /// Find the maximum of the wrapped collection
1079     /// </summary>
1080     /// <returns>The maximum</returns>
1081     public T FindMax() { return sorted.FindMax(); }
1082
1083
1084     /// <summary>
1085     /// </summary>
1086     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1087     /// <returns></returns>
1088     public T DeleteMax()
1089     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1090
1091     //TODO: we should guard the comparer!
1092     /// <summary>
1093     /// The comparer object supplied at creation time for the underlying collection
1094     /// </summary>
1095     /// <value>The comparer</value>
1096     public SCG.IComparer<T> Comparer { get { return sorted.Comparer; } }
1097     #endregion
1098
1099     #region IDirectedEnumerable<T> Members
1100
1101     IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
1102     { return Backwards(); }
1103
1104     #endregion
1105
1106     /// <summary>
1107     /// 
1108     /// </summary>
1109     /// <returns></returns>
1110     public override object Clone()
1111     {
1112       return new GuardedSorted<T>((ISorted<T>)(sorted.Clone()));
1113     }
1114
1115   }
1116
1117
1118
1119   /// <summary>
1120   /// Read-only wrapper for indexed sorted collections
1121   ///
1122   /// <i>Suitable for wrapping TreeSet, TreeBag and SortedArray</i>
1123   /// </summary>
1124   public class GuardedIndexedSorted<T> : GuardedSorted<T>, IIndexedSorted<T>
1125   {
1126     #region Fields
1127
1128     IIndexedSorted<T> indexedsorted;
1129
1130     #endregion
1131
1132     #region Constructor
1133
1134     /// <summary>
1135     /// Wrap an indexed sorted collection in a read-only wrapper
1136     /// </summary>
1137     /// <param name="list">the indexed sorted collection</param>
1138     public GuardedIndexedSorted(IIndexedSorted<T> list)
1139       : base(list)
1140     { this.indexedsorted = list; }
1141
1142     #endregion
1143
1144     #region IIndexedSorted<T> Members
1145
1146     /// <summary>
1147     /// Get the specified range from the wrapped collection. 
1148     /// (The current implementation erroneously does not wrap the result.)
1149     /// </summary>
1150     /// <param name="bot"></param>
1151     /// <returns></returns>
1152     public new IDirectedCollectionValue<T> RangeFrom(T bot)
1153     { return indexedsorted.RangeFrom(bot); }
1154
1155
1156     /// <summary>
1157     /// Get the specified range from the wrapped collection. 
1158     /// (The current implementation erroneously does not wrap the result.)
1159     /// </summary>
1160     /// <param name="bot"></param>
1161     /// <param name="top"></param>
1162     /// <returns></returns>
1163     public new IDirectedCollectionValue<T> RangeFromTo(T bot, T top)
1164     { return indexedsorted.RangeFromTo(bot, top); }
1165
1166
1167     /// <summary>
1168     /// Get the specified range from the wrapped collection. 
1169     /// (The current implementation erroneously does not wrap the result.)
1170     /// </summary>
1171     /// <param name="top"></param>
1172     /// <returns></returns>
1173     public new IDirectedCollectionValue<T> RangeTo(T top)
1174     { return indexedsorted.RangeTo(top); }
1175
1176
1177     /// <summary>
1178     /// Report the number of items in the specified range of the wrapped collection
1179     /// </summary>
1180     /// <param name="bot"></param>
1181     /// <returns></returns>
1182     public int CountFrom(T bot) { return indexedsorted.CountFrom(bot); }
1183
1184
1185     /// <summary>
1186     /// Report the number of items in the specified range of the wrapped collection
1187     /// </summary>
1188     /// <param name="bot"></param>
1189     /// <param name="top"></param>
1190     /// <returns></returns>
1191     public int CountFromTo(T bot, T top) { return indexedsorted.CountFromTo(bot, top); }
1192
1193
1194     /// <summary>
1195     /// Report the number of items in the specified range of the wrapped collection
1196     /// </summary>
1197     /// <param name="top"></param>
1198     /// <returns></returns>
1199     public int CountTo(T top) { return indexedsorted.CountTo(top); }
1200
1201
1202     /// <summary>
1203     /// Run FindAll on the wrapped collection with the indicated filter.
1204     /// The result will <b>not</b> be read-only.
1205     /// </summary>
1206     /// <param name="f"></param>
1207     /// <returns></returns>
1208     public IIndexedSorted<T> FindAll(Fun<T, bool> f)
1209     { return indexedsorted.FindAll(f); }
1210
1211
1212     /// <summary>
1213     /// Run Map on the wrapped collection with the indicated mapper.
1214     /// The result will <b>not</b> be read-only.
1215     /// </summary>
1216     /// <param name="m"></param>
1217     /// <param name="c">The comparer to use in the result</param>
1218     /// <returns></returns>
1219     public IIndexedSorted<V> Map<V>(Fun<T, V> m, SCG.IComparer<V> c)
1220     { return indexedsorted.Map(m, c); }
1221
1222     #endregion
1223
1224     #region IIndexed<T> Members
1225
1226     /// <summary>
1227     /// 
1228     /// </summary>
1229     /// <value>The i'th item of the wrapped sorted collection</value>
1230     public T this[int i] { get { return indexedsorted[i]; } }
1231
1232     /// <summary>
1233     /// 
1234     /// </summary>
1235     /// <value></value>
1236     public virtual Speed IndexingSpeed { get { return indexedsorted.IndexingSpeed; } }
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>(indexedsorted[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 indexedsorted.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 indexedsorted.LastIndexOf(item); }
1258
1259
1260     /// <summary>
1261     /// </summary>
1262     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1263     /// <param name="i"></param>
1264     /// <returns></returns>
1265     public T RemoveAt(int i)
1266     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1267
1268
1269     /// <summary>
1270     /// </summary>
1271     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1272     /// <param name="start"></param>
1273     /// <param name="count"></param>
1274     public void RemoveInterval(int start, int count)
1275     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1276
1277     #endregion
1278
1279     #region IDirectedEnumerable<T> Members
1280
1281     IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
1282     { return Backwards(); }
1283
1284     #endregion
1285
1286     /// <summary>
1287     /// 
1288     /// </summary>
1289     /// <returns></returns>
1290     public override object Clone()
1291     {
1292       return new GuardedIndexedSorted<T>((IIndexedSorted<T>)(indexedsorted.Clone()));
1293     }
1294
1295   }
1296
1297
1298
1299   /// <summary>
1300   /// A read-only wrapper for a generic list collection
1301   /// <i>Suitable as a wrapper for LinkedList, HashedLinkedList, ArrayList and HashedArray.
1302   /// <see cref="T:C5.LinkedList`1"/>, 
1303   /// <see cref="T:C5.HashedLinkedList`1"/>, 
1304   /// <see cref="T:C5.ArrayList`1"/> or
1305   /// <see cref="T:C5.HashedArray`1"/>.
1306   /// </i>
1307   /// </summary>
1308   public class GuardedList<T> : GuardedSequenced<T>, IList<T>, SCG.IList<T>
1309   {
1310     #region Fields
1311
1312     IList<T> innerlist;
1313     GuardedList<T> underlying;
1314     bool slidableView = false;
1315
1316     #endregion
1317
1318     #region Constructor
1319
1320     /// <summary>
1321     /// Wrap a list in a read-only wrapper.  A list gets wrapped as read-only,
1322     /// a list view gets wrapped as read-only and non-slidable.
1323     /// </summary>
1324     /// <param name="list">The list</param>
1325     public GuardedList(IList<T> list)
1326       : base(list)
1327     {
1328       this.innerlist = list;
1329       // If wrapping a list view, make innerlist = the view, and make 
1330       // underlying = a guarded version of the view's underlying list
1331       if (list.Underlying != null)
1332         underlying = new GuardedList<T>(list.Underlying, null, false);
1333     }
1334
1335     GuardedList(IList<T> list, GuardedList<T> underlying, bool slidableView)
1336       : base(list)
1337     {
1338       this.innerlist = list; this.underlying = underlying; this.slidableView = slidableView;
1339     }
1340     #endregion
1341
1342     #region IList<T> Members
1343
1344     /// <summary>
1345     /// 
1346     /// </summary>
1347     /// <value>The first item of the wrapped list</value>
1348     public T First { get { return innerlist.First; } }
1349
1350
1351     /// <summary>
1352     /// 
1353     /// </summary>
1354     /// <value>The last item of the wrapped list</value>
1355     public T Last { get { return innerlist.Last; } }
1356
1357
1358     /// <summary>
1359     /// </summary>
1360     /// <exception cref="ReadOnlyCollectionException"> if used as setter</exception>
1361     /// <value>True if wrapped list has FIFO semantics for the Add(T item) and Remove() methods</value>
1362     public bool FIFO
1363     {
1364       get { return innerlist.FIFO; }
1365       set { throw new ReadOnlyCollectionException("List is read only"); }
1366     }
1367
1368     /// <summary>
1369     /// 
1370     /// </summary>
1371     public virtual bool IsFixedSize
1372     {
1373       get { return true; }
1374     }
1375
1376
1377     /// <summary>
1378     /// </summary>
1379     /// <exception cref="ReadOnlyCollectionException"> if used as setter</exception>
1380     /// <value>The i'th item of the wrapped list</value>
1381     public T this[int i]
1382     {
1383       get { return innerlist[i]; }
1384       set { throw new ReadOnlyCollectionException("List is read only"); }
1385     }
1386
1387     /// <summary>
1388     /// 
1389     /// </summary>
1390     /// <value></value>
1391     public virtual Speed IndexingSpeed { get { return innerlist.IndexingSpeed; } }
1392
1393     /// <summary>
1394     /// </summary>
1395     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1396     /// <param name="index"></param>
1397     /// <param name="item"></param>
1398     public void Insert(int index, T item)
1399     { throw new ReadOnlyCollectionException(); }
1400
1401     /// <summary>
1402     /// </summary>
1403     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1404     /// <param name="pointer"></param>
1405     /// <param name="item"></param>
1406     public void Insert(IList<T> pointer, T item)
1407     { throw new ReadOnlyCollectionException(); }
1408
1409     /// <summary>
1410     /// </summary>
1411     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1412     /// <param name="item"></param>
1413     public void InsertFirst(T item)
1414     { throw new ReadOnlyCollectionException("List is read only"); }
1415
1416     /// <summary>
1417     /// </summary>
1418     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1419     /// <param name="item"></param>
1420     public void InsertLast(T item)
1421     { throw new ReadOnlyCollectionException("List is read only"); }
1422
1423     /// <summary>
1424     /// </summary>
1425     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1426     /// <param name="item"></param>
1427     /// <param name="target"></param>
1428     public void InsertBefore(T item, T target)
1429     { throw new ReadOnlyCollectionException("List is read only"); }
1430
1431
1432     /// <summary>
1433     /// </summary>
1434     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1435     /// <param name="item"></param>
1436     /// <param name="target"></param>
1437     public void InsertAfter(T item, T target)
1438     { throw new ReadOnlyCollectionException("List is read only"); }
1439
1440
1441     /// <summary>
1442     /// </summary>
1443     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1444     /// <param name="i"></param>
1445     /// <param name="items"></param>
1446     public void InsertAll<U>(int i, SCG.IEnumerable<U> items) where U : T
1447     { throw new ReadOnlyCollectionException("List is read only"); }
1448
1449
1450     /// <summary>
1451     /// Perform FindAll on the wrapped list. The result is <b>not</b> necessarily read-only.
1452     /// </summary>
1453     /// <param name="filter">The filter to use</param>
1454     /// <returns></returns>
1455     public IList<T> FindAll(Fun<T, bool> filter) { return innerlist.FindAll(filter); }
1456
1457
1458     /// <summary>
1459     /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
1460     /// </summary>
1461     /// <typeparam name="V">The type of items of the new list</typeparam>
1462     /// <param name="mapper">The mapper to use.</param>
1463     /// <returns>The mapped list</returns>
1464     public IList<V> Map<V>(Fun<T, V> mapper) { return innerlist.Map(mapper); }
1465
1466     /// <summary>
1467     /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
1468     /// </summary>
1469     /// <typeparam name="V">The type of items of the new list</typeparam>
1470     /// <param name="mapper">The delegate defining the map.</param>
1471     /// <param name="itemequalityComparer">The itemequalityComparer to use for the new list</param>
1472     /// <returns>The new list.</returns>
1473     public IList<V> Map<V>(Fun<T, V> mapper, SCG.IEqualityComparer<V> itemequalityComparer) { return innerlist.Map(mapper, itemequalityComparer); }
1474
1475     /// <summary>
1476     /// </summary>
1477     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1478     /// <returns></returns>
1479     public T Remove() { throw new ReadOnlyCollectionException("List is read only"); }
1480
1481
1482     /// <summary>
1483     /// </summary>
1484     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1485     /// <returns></returns>
1486     public T RemoveFirst() { throw new ReadOnlyCollectionException("List is read only"); }
1487
1488
1489     /// <summary>
1490     /// </summary>
1491     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1492     /// <returns></returns>
1493     public T RemoveLast() { throw new ReadOnlyCollectionException("List is read only"); }
1494
1495
1496     /// <summary>
1497     /// Create the indicated view on the wrapped list and wrap it read-only.
1498     /// </summary>
1499     /// <param name="start"></param>
1500     /// <param name="count"></param>
1501     /// <returns></returns>
1502     public IList<T> View(int start, int count)
1503     {
1504       IList<T> view = innerlist.View(start, count);
1505       return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);
1506     }
1507
1508     /// <summary>
1509     /// Create the indicated view on the wrapped list and wrap it read-only.
1510     /// </summary>
1511     /// <param name="item"></param>
1512     /// <returns></returns>
1513     public IList<T> ViewOf(T item)
1514     {
1515       IList<T> view = innerlist.ViewOf(item);
1516       return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);
1517     }
1518
1519     /// <summary>
1520     /// Create the indicated view on the wrapped list and wrap it read-only.
1521     /// </summary>
1522     /// <param name="item"></param>
1523     /// <returns></returns>
1524     public IList<T> LastViewOf(T item)
1525     {
1526       IList<T> view = innerlist.LastViewOf(item);
1527       return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);
1528     }
1529
1530
1531     /// <summary>
1532     /// </summary>
1533     /// <value>The wrapped underlying list of the wrapped view </value>
1534     public IList<T> Underlying { get { return underlying; } }
1535
1536
1537     /// <summary>
1538     /// 
1539     /// </summary>
1540     /// <value>The offset of the wrapped list as a view.</value>
1541     public int Offset { get { return innerlist.Offset; } }
1542
1543     /// <summary>
1544     /// 
1545     /// </summary>
1546     /// <value></value>
1547     public virtual bool IsValid { get { return innerlist.IsValid; } }
1548
1549     /// <summary>
1550     /// </summary>
1551     /// <exception cref="ReadOnlyCollectionException"> if this is a wrapped view and not a view that was made on a wrapper</exception>
1552     /// <param name="offset"></param>
1553     public IList<T> Slide(int offset)
1554     {
1555       if (slidableView)
1556       {
1557         innerlist.Slide(offset);
1558         return this;
1559       }
1560       else
1561         throw new ReadOnlyCollectionException("List is read only");
1562     }
1563
1564
1565     /// <summary>
1566     /// </summary>
1567     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1568     /// <param name="offset"></param>
1569     /// <param name="size"></param>
1570     public IList<T> Slide(int offset, int size)
1571     {
1572       if (slidableView)
1573       {
1574         innerlist.Slide(offset, size);
1575         return this;
1576       }
1577       else
1578         throw new ReadOnlyCollectionException("List is read only");
1579     }
1580
1581
1582     /// <summary>
1583     /// 
1584     /// </summary>
1585     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1586     /// <param name="offset"></param>
1587     /// <returns></returns>
1588     public bool TrySlide(int offset)
1589     {
1590       if (slidableView)
1591         return innerlist.TrySlide(offset);
1592       else
1593         throw new ReadOnlyCollectionException("List is read only");
1594     }
1595
1596     /// <summary>
1597     /// 
1598     /// </summary>
1599     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1600     /// <param name="offset"></param>
1601     /// <param name="size"></param>
1602     /// <returns></returns>
1603     public bool TrySlide(int offset, int size)
1604     {
1605       if (slidableView)
1606         return innerlist.TrySlide(offset, size);
1607       else
1608         throw new ReadOnlyCollectionException("List is read only");
1609     }
1610
1611     /// <summary>
1612     /// 
1613     /// </summary>
1614     /// <param name="otherView"></param>
1615     /// <returns></returns>
1616     public IList<T> Span(IList<T> otherView)
1617     {
1618       GuardedList<T> otherGuardedList = otherView as GuardedList<T>;
1619       if (otherGuardedList == null)
1620         throw new IncompatibleViewException();
1621       IList<T> span = innerlist.Span(otherGuardedList.innerlist);
1622       if (span == null)
1623         return null;
1624       return new GuardedList<T>(span, underlying ?? otherGuardedList.underlying ?? this, true);
1625     }
1626
1627     /// <summary>
1628     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1629     /// </summary>
1630     public void Reverse() { throw new ReadOnlyCollectionException("List is read only"); }
1631
1632
1633     /// <summary>
1634     /// </summary>
1635     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1636     /// <param name="start"></param>
1637     /// <param name="count"></param>
1638     public void Reverse(int start, int count)
1639     { throw new ReadOnlyCollectionException("List is read only"); }
1640
1641
1642     /// <summary>
1643     /// Check if wrapped list is sorted according to the default sorting order
1644     /// for the item type T, as defined by the <see cref="T:C5.Comparer`1"/> class 
1645     /// </summary>
1646     /// <exception cref="NotComparableException">if T is not comparable</exception>
1647     /// <returns>True if the list is sorted, else false.</returns>
1648     public bool IsSorted() { return innerlist.IsSorted(Comparer<T>.Default); }
1649
1650     /// <summary>
1651     /// Check if wrapped list is sorted
1652     /// </summary>
1653     /// <param name="c">The sorting order to use</param>
1654     /// <returns>True if sorted</returns>
1655     public bool IsSorted(SCG.IComparer<T> c) { return innerlist.IsSorted(c); }
1656
1657
1658     /// <summary>
1659     /// </summary>
1660     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1661     public void Sort()
1662     { throw new ReadOnlyCollectionException("List is read only"); }
1663
1664
1665     /// <summary>
1666     /// </summary>
1667     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1668     /// <param name="c"></param>
1669     public void Sort(SCG.IComparer<T> c)
1670     { throw new ReadOnlyCollectionException("List is read only"); }
1671
1672     /// <summary>
1673     /// </summary>
1674     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1675     public void Shuffle()
1676     { throw new ReadOnlyCollectionException("List is read only"); }
1677
1678
1679     /// <summary>
1680     /// </summary>
1681     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1682     /// <param name="rnd"></param>
1683     public void Shuffle(Random rnd)
1684     { throw new ReadOnlyCollectionException("List is read only"); }
1685
1686     #endregion
1687
1688     #region IIndexed<T> Members
1689
1690     /// <summary> </summary>
1691     /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>
1692     public IDirectedCollectionValue<T> this[int start, int end]
1693     { get { return new GuardedDirectedCollectionValue<T>(innerlist[start, end]); } }
1694
1695
1696     /// <summary>
1697     /// Find the (first) index of an item in the wrapped collection
1698     /// </summary>
1699     /// <param name="item"></param>
1700     /// <returns></returns>
1701     public int IndexOf(T item) { return innerlist.IndexOf(item); }
1702
1703
1704     /// <summary>
1705     /// Find the last index of an item in the wrapped collection
1706     /// </summary>
1707     /// <param name="item"></param>
1708     /// <returns></returns>
1709     public int LastIndexOf(T item) { return innerlist.LastIndexOf(item); }
1710
1711
1712     /// <summary>
1713     /// </summary>
1714     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1715     /// <param name="i"></param>
1716     /// <returns></returns>
1717     public T RemoveAt(int i)
1718     { throw new ReadOnlyCollectionException("List is read only"); }
1719
1720
1721     /// <summary>
1722     /// </summary>
1723     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1724     /// <param name="start"></param>
1725     /// <param name="count"></param>
1726     public void RemoveInterval(int start, int count)
1727     { throw new ReadOnlyCollectionException("List is read only"); }
1728
1729     #endregion
1730
1731     #region IDirectedEnumerable<T> Members
1732
1733     IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
1734     { return Backwards(); }
1735
1736     #endregion
1737
1738     #region IStack<T> Members
1739
1740
1741     /// <summary>
1742     /// 
1743     /// </summary>
1744     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1745     /// <returns>-</returns>
1746     public void Push(T item)
1747     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1748
1749     /// <summary>
1750     /// 
1751     /// </summary>
1752     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1753     /// <returns>-</returns>
1754     public T Pop()
1755     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1756
1757     #endregion
1758
1759     #region IQueue<T> Members
1760
1761     /// <summary>
1762     /// 
1763     /// </summary>
1764     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1765     /// <returns>-</returns>
1766     public void Enqueue(T item)
1767     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1768
1769     /// <summary>
1770     /// 
1771     /// </summary>
1772     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1773     /// <returns>-</returns>
1774     public T Dequeue()
1775     { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
1776
1777     #endregion
1778
1779     #region IDisposable Members
1780
1781     /// <summary>
1782     /// Ignore: this may be called by a foreach or using statement.
1783     /// </summary>
1784     public void Dispose() { }
1785
1786     #endregion
1787
1788     /// <summary>
1789     /// 
1790     /// </summary>
1791     /// <returns></returns>
1792     public override object Clone()
1793     {
1794       return new GuardedList<T>((IList<T>)(innerlist.Clone()));
1795     }
1796
1797     #region System.Collections.Generic.IList<T> Members
1798
1799     void System.Collections.Generic.IList<T>.RemoveAt(int index)
1800     {
1801       throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
1802     }
1803
1804     void System.Collections.Generic.ICollection<T>.Add(T item)
1805     {
1806       throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
1807     }
1808
1809     #endregion
1810
1811     #region System.Collections.ICollection Members
1812
1813     bool System.Collections.ICollection.IsSynchronized
1814     {
1815       get { return false; }
1816     }
1817
1818     [Obsolete]
1819     Object System.Collections.ICollection.SyncRoot
1820     {
1821       get { return innerlist.SyncRoot; }
1822     }
1823
1824     void System.Collections.ICollection.CopyTo(Array arr, int index)
1825     {
1826       if (index < 0 || index + Count > arr.Length)
1827         throw new ArgumentOutOfRangeException();
1828
1829       foreach (T item in this)
1830         arr.SetValue(item, index++);
1831     }
1832
1833     #endregion
1834
1835     #region System.Collections.IList Members
1836     
1837     Object System.Collections.IList.this[int index]
1838     {
1839       get { return this[index]; }
1840       set
1841       {
1842         throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
1843       }
1844     }
1845
1846     int System.Collections.IList.Add(Object o)
1847     {
1848       throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
1849     }
1850
1851     bool System.Collections.IList.Contains(Object o)
1852     {
1853       return Contains((T)o);
1854     }
1855
1856     int System.Collections.IList.IndexOf(Object o)
1857     {
1858       return Math.Max(-1, IndexOf((T)o));
1859     }
1860
1861     void System.Collections.IList.Insert(int index, Object o)
1862     {
1863       throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
1864     }
1865
1866     void System.Collections.IList.Remove(Object o)
1867     {
1868       throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
1869     }
1870
1871     void System.Collections.IList.RemoveAt(int index)
1872     {
1873       throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
1874     }
1875
1876     #endregion
1877   }
1878
1879   /// <summary>
1880   /// A read-only wrapper for a generic indexable queue (allows indexing).
1881   /// 
1882   /// <para>Suitable for wrapping a <see cref="T:C5.CircularQueue`1"/></para>
1883   /// </summary>
1884   /// <typeparam name="T">The item type.</typeparam>
1885   public class GuardedQueue<T> : GuardedDirectedCollectionValue<T>, IQueue<T>
1886   {
1887     #region Fields
1888
1889     IQueue<T> queue;
1890
1891     #endregion
1892
1893     #region Constructor
1894
1895     /// <summary>
1896     /// Wrap a queue in a read-only wrapper
1897     /// </summary>
1898     /// <param name="queue">The queue</param>
1899     public GuardedQueue(IQueue<T> queue) : base(queue) { this.queue = queue; }
1900
1901     #endregion
1902
1903     #region IQueue<T> Members
1904     /// <summary>
1905     /// 
1906     /// </summary>
1907     /// <value></value>
1908     public bool AllowsDuplicates { get { return queue.AllowsDuplicates; } }
1909
1910     /// <summary>
1911     /// Index into the wrapped queue
1912     /// </summary>
1913     /// <param name="i"></param>
1914     /// <returns></returns>
1915     public T this[int i] { get { return queue[i]; } }
1916
1917     /// <summary>
1918     /// 
1919     /// </summary>
1920     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1921     /// <returns>-</returns>
1922     public void Enqueue(T item)
1923     { throw new ReadOnlyCollectionException("Queue cannot be modified through this guard object"); }
1924
1925     /// <summary>
1926     /// 
1927     /// </summary>
1928     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
1929     /// <returns>-</returns>
1930     public T Dequeue()
1931     { throw new ReadOnlyCollectionException("Queue cannot be modified through this guard object"); }
1932
1933     #endregion
1934   }
1935
1936   /// <summary>
1937   /// A read-only wrapper for a dictionary.
1938   ///
1939   /// <i>Suitable for wrapping a HashDictionary. <see cref="T:C5.HashDictionary`2"/></i>
1940   /// </summary>
1941   public class GuardedDictionary<K, V> : GuardedCollectionValue<KeyValuePair<K, V>>, IDictionary<K, V>
1942   {
1943     #region Fields
1944
1945     IDictionary<K, V> dict;
1946
1947     #endregion
1948
1949     #region Constructor
1950
1951     /// <summary>
1952     /// Wrap a dictionary in a read-only wrapper
1953     /// </summary>
1954     /// <param name="dict">the dictionary</param>
1955     public GuardedDictionary(IDictionary<K, V> dict) : base(dict) { this.dict = dict; }
1956
1957     #endregion
1958
1959     #region IDictionary<K,V> Members
1960
1961     /// <summary>
1962     /// 
1963     /// </summary>
1964     /// <value></value>
1965     public SCG.IEqualityComparer<K> EqualityComparer { get { return dict.EqualityComparer; } }
1966
1967     /// <summary>
1968     /// </summary>
1969     /// <exception cref="ReadOnlyCollectionException"> since this is a
1970     /// read-only wrappper if used as a setter</exception>
1971     /// <value>Get the value corresponding to a key in the wrapped dictionary</value>
1972     public V this[K key]
1973     {
1974       get { return dict[key]; }
1975       set { throw new ReadOnlyCollectionException(); }
1976     }
1977
1978     /// <summary>
1979     /// (This is a read-only wrapper)
1980     /// </summary>
1981     /// <value>True</value>
1982     public bool IsReadOnly { get { return true; } }
1983
1984
1985     //TODO: guard with a read-only wrapper? Probably so!
1986     /// <summary> </summary>
1987     /// <value>The collection of keys of the wrapped dictionary</value>
1988     public ICollectionValue<K> Keys
1989     { get { return dict.Keys; } }
1990
1991
1992     /// <summary> </summary>
1993     /// <value>The collection of values of the wrapped dictionary</value>
1994     public ICollectionValue<V> Values { get { return dict.Values; } }
1995
1996     /// <summary>
1997     /// 
1998     /// </summary>
1999     public virtual Fun<K, V> Fun { get { return delegate(K k) { return this[k]; }; } }
2000
2001     /// <summary>
2002     /// </summary>
2003     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2004     /// <param name="key"></param>
2005     /// <param name="val"></param>
2006     public void Add(K key, V val)
2007     { throw new ReadOnlyCollectionException(); }
2008
2009     /// <summary>
2010     /// 
2011     /// </summary>
2012     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2013     /// <param name="items"></param>
2014     public void AddAll<L, W>(SCG.IEnumerable<KeyValuePair<L, W>> items)
2015       where L : K
2016       where W : V
2017     { throw new ReadOnlyCollectionException(); }
2018
2019     /// <summary>
2020     /// </summary>
2021     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2022     /// <param name="key"></param>
2023     /// <returns></returns>
2024     public bool Remove(K key)
2025     { throw new ReadOnlyCollectionException(); }
2026
2027
2028     /// <summary>
2029     /// </summary>
2030     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2031     /// <param name="key"></param>
2032     /// <param name="val"></param>
2033     /// <returns></returns>
2034     public bool Remove(K key, out V val)
2035     { throw new ReadOnlyCollectionException(); }
2036
2037
2038     /// <summary>
2039     /// </summary>
2040     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2041     public void Clear()
2042     { throw new ReadOnlyCollectionException(); }
2043
2044     /// <summary>
2045     /// 
2046     /// </summary>
2047     /// <value></value>
2048     public Speed ContainsSpeed { get { return dict.ContainsSpeed; } }
2049
2050     /// <summary>
2051     /// Check if the wrapped dictionary contains a specific key
2052     /// </summary>
2053     /// <param name="key">The key</param>
2054     /// <returns>True if it does</returns>
2055     public bool Contains(K key) { return dict.Contains(key); }
2056
2057     /// <summary>
2058     /// 
2059     /// </summary>
2060     /// <param name="keys"></param>
2061     /// <returns></returns>
2062     public bool ContainsAll<H>(SCG.IEnumerable<H> keys) where H : K { return dict.ContainsAll(keys); }
2063
2064     /// <summary>
2065     /// Search for a key in the wrapped dictionary, reporting the value if found
2066     /// </summary>
2067     /// <param name="key">The key</param>
2068     /// <param name="val">On exit: the value if found</param>
2069     /// <returns>True if found</returns>
2070     public bool Find(K key, out V val) { return dict.Find(key, out val); }
2071
2072     /// <summary>
2073     /// Search for a key in the wrapped dictionary, reporting the value if found
2074     /// </summary>
2075     /// <param name="key">The key</param>
2076     /// <param name="val">On exit: the value if found</param>
2077     /// <returns>True if found</returns>
2078     public bool Find(ref K key, out V val) { return dict.Find(ref key, out val); }
2079
2080
2081     /// <summary>
2082     /// </summary>
2083     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2084     /// <param name="key"></param>
2085     /// <param name="val"></param>
2086     /// <returns></returns>
2087     public bool Update(K key, V val)
2088     { throw new ReadOnlyCollectionException(); }
2089
2090
2091     /// <summary>
2092     /// </summary>
2093     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2094     /// <param name="key"></param>
2095     /// <param name="val"></param>
2096     /// <param name="oldval"></param>
2097     /// <returns></returns>
2098     public bool Update(K key, V val, out V oldval)
2099     { throw new ReadOnlyCollectionException(); }
2100
2101
2102     /// <summary>
2103     /// </summary>
2104     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2105     /// <param name="key"></param>
2106     /// <param name="val"></param>
2107     /// <returns></returns>
2108     public bool FindOrAdd(K key, ref V val)
2109     { throw new ReadOnlyCollectionException(); }
2110
2111
2112     /// <summary>
2113     /// </summary>
2114     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2115     /// <param name="key"></param>
2116     /// <param name="val"></param>
2117     /// <returns></returns>
2118     public bool UpdateOrAdd(K key, V val)
2119     { throw new ReadOnlyCollectionException(); }
2120
2121     /// <summary>
2122     /// </summary>
2123     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2124     /// <param name="key"></param>
2125     /// <param name="val"></param>
2126     /// <param name="oldval"></param>
2127     /// <returns></returns>
2128     public bool UpdateOrAdd(K key, V val, out V oldval)
2129     { throw new ReadOnlyCollectionException(); }
2130
2131
2132     /// <summary>
2133     /// Check the internal consistency of the wrapped dictionary
2134     /// </summary>
2135     /// <returns>True if check passed</returns>
2136     public bool Check() { return dict.Check(); }
2137
2138     #endregion
2139
2140     /// <summary>
2141     /// 
2142     /// </summary>
2143     /// <returns></returns>
2144     public virtual object Clone()
2145     {
2146       return new GuardedDictionary<K, V>((IDictionary<K, V>)(dict.Clone()));
2147     }
2148   }
2149
2150
2151
2152   /// <summary>
2153   /// A read-only wrapper for a sorted dictionary.
2154   ///
2155   /// <i>Suitable for wrapping a Dictionary. <see cref="T:C5.Dictionary`2"/></i>
2156   /// </summary>
2157   public class GuardedSortedDictionary<K, V> : GuardedDictionary<K, V>, ISortedDictionary<K, V>
2158   {
2159     #region Fields
2160
2161     ISortedDictionary<K, V> sorteddict;
2162
2163     #endregion
2164
2165     #region Constructor
2166
2167     /// <summary>
2168     /// Wrap a sorted dictionary in a read-only wrapper
2169     /// </summary>
2170     /// <param name="sorteddict">the dictionary</param>
2171     public GuardedSortedDictionary(ISortedDictionary<K, V> sorteddict)
2172       : base(sorteddict)
2173     { this.sorteddict = sorteddict; }
2174
2175     #endregion
2176
2177     #region ISortedDictionary<K,V> Members
2178
2179     /// <summary>
2180     /// The key comparer used by this dictionary.
2181     /// </summary>
2182     /// <value></value>
2183     public SCG.IComparer<K> Comparer { get { return sorteddict.Comparer; } }
2184
2185     /// <summary>
2186     /// 
2187     /// </summary>
2188     /// <value></value>
2189     public new ISorted<K> Keys { get { return null; } }
2190
2191     /// <summary>
2192     /// Find the entry in the dictionary whose key is the
2193     /// predecessor of the specified key.
2194     /// </summary>
2195     /// <param name="key">The key</param>
2196     /// <param name="res">The predecessor, if any</param>
2197     /// <returns>True if key has a predecessor</returns>
2198     public bool TryPredecessor(K key, out KeyValuePair<K, V> res)
2199     {
2200       return sorteddict.TryPredecessor(key, out res);
2201     }
2202
2203     /// <summary>
2204     /// Find the entry in the dictionary whose key is the
2205     /// successor of the specified key.
2206     /// </summary>
2207     /// <param name="key">The key</param>
2208     /// <param name="res">The successor, if any</param>
2209     /// <returns>True if the key has a successor</returns>
2210     public bool TrySuccessor(K key, out KeyValuePair<K, V> res)
2211     {
2212       return sorteddict.TrySuccessor(key, out res);
2213     }
2214
2215     /// <summary>
2216     /// Find the entry in the dictionary whose key is the
2217     /// weak predecessor of the specified key.
2218     /// </summary>
2219     /// <param name="key">The key</param>
2220     /// <param name="res">The predecessor, if any</param>
2221     /// <returns>True if key has a weak predecessor</returns>
2222     public bool TryWeakPredecessor(K key, out KeyValuePair<K, V> res)
2223     {
2224       return sorteddict.TryWeakPredecessor(key, out res);
2225     }
2226
2227     /// <summary>
2228     /// Find the entry in the dictionary whose key is the
2229     /// weak successor of the specified key.
2230     /// </summary>
2231     /// <param name="key">The key</param>
2232     /// <param name="res">The weak successor, if any</param>
2233     /// <returns>True if the key has a weak successor</returns>
2234     public bool TryWeakSuccessor(K key, out KeyValuePair<K, V> res)
2235     {
2236       return sorteddict.TryWeakSuccessor(key, out res);
2237     }
2238
2239     /// <summary>
2240     /// Get the entry in the wrapped dictionary whose key is the
2241     /// predecessor of a specified key.
2242     /// </summary>
2243     /// <exception cref="NoSuchItemException"> if no such entry exists </exception>    
2244     /// <param name="key">The key</param>
2245     /// <returns>The entry</returns>
2246     public KeyValuePair<K, V> Predecessor(K key)
2247     { return sorteddict.Predecessor(key); }
2248
2249     /// <summary>
2250     /// Get the entry in the wrapped dictionary whose key is the
2251     /// successor of a specified key.
2252     /// </summary>
2253     /// <exception cref="NoSuchItemException"> if no such entry exists </exception>    
2254     /// <param name="key">The key</param>
2255     /// <returns>The entry</returns>
2256     public KeyValuePair<K, V> Successor(K key)
2257     { return sorteddict.Successor(key); }
2258
2259
2260     /// <summary>
2261     /// Get the entry in the wrapped dictionary whose key is the
2262     /// weak predecessor of a specified key.
2263     /// </summary>
2264     /// <exception cref="NoSuchItemException"> if no such entry exists </exception>    
2265     /// <param name="key">The key</param>
2266     /// <returns>The entry</returns>
2267     public KeyValuePair<K, V> WeakPredecessor(K key)
2268     { return sorteddict.WeakPredecessor(key); }
2269
2270
2271     /// <summary>
2272     /// Get the entry in the wrapped dictionary whose key is the
2273     /// weak successor of a specified key.
2274     /// </summary>
2275     /// <exception cref="NoSuchItemException"> if no such entry exists </exception>    
2276     /// <param name="key">The key</param>
2277     /// <returns>The entry</returns>
2278     public KeyValuePair<K, V> WeakSuccessor(K key)
2279     { return sorteddict.WeakSuccessor(key); }
2280
2281     /// <summary>
2282     /// 
2283     /// </summary>
2284     /// <returns></returns>
2285     public KeyValuePair<K, V> FindMin()
2286     {
2287       return sorteddict.FindMin();
2288     }
2289
2290     /// <summary>
2291     /// 
2292     /// </summary>
2293     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2294     /// <returns></returns>
2295     public KeyValuePair<K, V> DeleteMin()
2296     { throw new ReadOnlyCollectionException(); }
2297
2298     /// <summary>
2299     /// 
2300     /// </summary>
2301     /// <returns></returns>
2302     public KeyValuePair<K, V> FindMax()
2303     {
2304       return sorteddict.FindMax();
2305     }
2306
2307     /// <summary>
2308     /// 
2309     /// </summary>
2310     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2311     /// <returns></returns>
2312     public KeyValuePair<K, V> DeleteMax()
2313     { throw new ReadOnlyCollectionException(); }
2314
2315     /// <summary>
2316     /// 
2317     /// </summary>
2318     /// <param name="c"></param>
2319     /// <param name="lowEntry"></param>
2320     /// <param name="lowIsValid"></param>
2321     /// <param name="highEntry"></param>
2322     /// <param name="highIsValid"></param>
2323     /// <returns></returns>
2324     public bool Cut(IComparable<K> c, out KeyValuePair<K, V> lowEntry, out bool lowIsValid, out KeyValuePair<K, V> highEntry, out bool highIsValid)
2325     {
2326       return sorteddict.Cut(c, out lowEntry, out lowIsValid, out highEntry, out highIsValid); ;
2327     }
2328
2329     /// <summary>
2330     /// 
2331     /// </summary>
2332     /// <param name="bot"></param>
2333     /// <returns></returns>
2334     public IDirectedEnumerable<KeyValuePair<K, V>> RangeFrom(K bot)
2335     {
2336       return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeFrom(bot));
2337     }
2338
2339     /// <summary>
2340     /// 
2341     /// </summary>
2342     /// <param name="bot"></param>
2343     /// <param name="top"></param>
2344     /// <returns></returns>
2345     public IDirectedEnumerable<KeyValuePair<K, V>> RangeFromTo(K bot, K top)
2346     {
2347       return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeFromTo(bot, top));
2348     }
2349
2350     /// <summary>
2351     /// 
2352     /// </summary>
2353     /// <param name="top"></param>
2354     /// <returns></returns>
2355     public IDirectedEnumerable<KeyValuePair<K, V>> RangeTo(K top)
2356     {
2357       return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeTo(top));
2358     }
2359
2360     /// <summary>
2361     /// 
2362     /// </summary>
2363     /// <returns></returns>
2364     public IDirectedCollectionValue<KeyValuePair<K, V>> RangeAll()
2365     {
2366       return new GuardedDirectedCollectionValue<KeyValuePair<K, V>>(sorteddict.RangeAll());
2367     }
2368
2369     /// <summary>
2370     /// 
2371     /// </summary>
2372     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2373     /// <param name="items"></param>
2374     public void AddSorted(System.Collections.Generic.IEnumerable<KeyValuePair<K, V>> items)
2375     { throw new ReadOnlyCollectionException(); }
2376
2377     /// <summary>
2378     /// 
2379     /// </summary>
2380     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2381     /// <param name="low"></param>
2382     public void RemoveRangeFrom(K low)
2383     { throw new ReadOnlyCollectionException(); }
2384
2385     /// <summary>
2386     /// 
2387     /// </summary>
2388     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2389     /// <param name="low"></param>
2390     /// <param name="hi"></param>
2391     public void RemoveRangeFromTo(K low, K hi)
2392     { throw new ReadOnlyCollectionException(); }
2393
2394     /// <summary>
2395     /// 
2396     /// </summary>
2397     /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
2398     /// <param name="hi"></param>
2399     public void RemoveRangeTo(K hi)
2400     { throw new ReadOnlyCollectionException(); }
2401
2402     #endregion
2403   }
2404
2405 }