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