**** Merged from MCS ****
[mono-project.git] / mcs / class / Mono.C5 / Wrappers.cs
blobde1a11f51d1ac7ad54844daa40cf459b90dae474
1 #if NET_2_0
2 /*
3 Copyright (c) 2003-2004 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 SOFTWARE.
23 using System;
24 using System.Diagnostics;
25 using MSG = System.Collections.Generic;
26 namespace C5
28 /// <summary>
29 /// A read-only wrapper class for a generic enumerator
30 /// </summary>
31 public class GuardedEnumerator<T>: MSG.IEnumerator<T>
33 #region Fields
35 MSG.IEnumerator<T> enumerator;
37 #endregion
39 #region Constructor
41 /// <summary>
42 /// Create a wrapper around a generic enumerator
43 /// </summary>
44 /// <param name="enumerator">The enumerator to wrap</param>
45 public GuardedEnumerator(MSG.IEnumerator<T> enumerator)
46 { this.enumerator = enumerator; }
48 #endregion
50 #region IEnumerator<T> Members
52 /// <summary>
53 /// Move wrapped enumerator to next item, or the first item if
54 /// this is the first call to MoveNext.
55 /// </summary>
56 /// <returns>True if enumerator is valid now</returns>
57 public bool MoveNext() { return enumerator.MoveNext(); }
60 /// <summary>
61 /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
62 /// </summary>
63 /// <value>The current item of the wrapped enumerator.</value>
64 public T Current { get { return enumerator.Current; } }
66 #endregion
68 #region IDisposable Members
70 /// <summary>
71 /// Dispose wrapped enumerator
72 /// </summary>
73 public void Dispose() { enumerator.Dispose(); }
75 #endregion
80 /// <summary>
81 /// A read-only wrapper class for a generic enumerable
82 ///
83 /// <p>This is mainly interesting as a base of other guard classes</p>
84 /// </summary>
85 public class GuardedEnumerable<T>: MSG.IEnumerable<T>
87 #region Fields
89 MSG.IEnumerable<T> enumerable;
91 #endregion
93 #region Constructor
95 /// <summary>
96 /// Wrap an enumerable in a read-only wrapper
97 /// </summary>
98 /// <param name="enumerable">The enumerable to wrap</param>
99 public GuardedEnumerable(MSG.IEnumerable<T> enumerable)
100 { this.enumerable = enumerable; }
102 #endregion
104 #region MSG.IEnumerable<T> Members
106 /// <summary>
107 /// Get an enumerator from the wrapped enumerable
108 /// </summary>
109 /// <returns>The enumerator (itself wrapped)</returns>
110 public MSG.IEnumerator<T> GetEnumerator()
111 { return new GuardedEnumerator<T>(enumerable.GetEnumerator()); }
113 #endregion
118 /// <summary>
119 /// A read-only wrapper for a generic directed enumerable
121 /// <p>This is mainly interesting as a base of other guard classes</p>
122 /// </summary>
123 public class GuardedDirectedEnumerable<T>: GuardedEnumerable<T>, IDirectedEnumerable<T>
125 #region Fields
127 IDirectedEnumerable<T> directedenumerable;
129 #endregion
131 #region Constructor
133 /// <summary>
134 /// Wrap a directed enumerable in a read-only wrapper
135 /// </summary>
136 /// <param name="directedenumerable">the collection to wrap</param>
137 public GuardedDirectedEnumerable(IDirectedEnumerable<T> directedenumerable)
138 : base(directedenumerable)
139 { this.directedenumerable = directedenumerable; }
141 #endregion
143 #region IDirectedEnumerable<T> Members
145 /// <summary>
146 /// Get a enumerable that enumerates the wrapped collection in the opposite direction
147 /// </summary>
148 /// <returns>The mirrored enumerable</returns>
149 public IDirectedEnumerable<T> Backwards()
150 { return new GuardedDirectedEnumerable<T>(directedenumerable.Backwards()); }
153 /// <summary>
154 /// <code>Forwards</code> if same, else <code>Backwards</code>
155 /// </summary>
156 /// <value>The enumeration direction relative to the original collection.</value>
157 public EnumerationDirection Direction
158 { get { return directedenumerable.Direction; } }
160 #endregion
165 /// <summary>
166 /// A read-only wrapper for an ICollectionValue&lt;T&gt;
168 /// <p>This is mainly interesting as a base of other guard classes</p>
169 /// </summary>
170 public class GuardedCollectionValue<T>: GuardedEnumerable<T>, ICollectionValue<T>
172 #region Fields
174 ICollectionValue<T> collection;
176 #endregion
178 #region Constructor
180 /// <summary>
181 /// Wrap a ICollectionValue&lt;T&gt; in a read-only wrapper
182 /// </summary>
183 /// <param name="collection">the collection to wrap</param>
184 public GuardedCollectionValue(ICollectionValue<T> collection) : base(collection)
185 { this.collection = collection; }
187 #endregion
189 #region ICollection<T> Members
191 /// <summary>
192 /// Get the size of the wrapped collection
193 /// </summary>
194 /// <value>The size</value>
195 public int Count { get { return collection.Count; } }
197 /// <summary>
198 /// The value is symbolic indicating the type of asymptotic complexity
199 /// in terms of the size of this collection (worst-case or amortized as
200 /// relevant).
201 /// </summary>
202 /// <value>A characterization of the speed of the
203 /// <code>Count</code> property in this collection.</value>
204 public Speed CountSpeed { get { return collection.CountSpeed; } }
206 /// <summary>
207 /// Copy the items of the wrapped collection to an array
208 /// </summary>
209 /// <param name="a">The array</param>
210 /// <param name="i">Starting offset</param>
211 public void CopyTo(T[] a, int i) { collection.CopyTo(a, i); }
213 /// <summary>
214 /// Create an array from the items of the wrapped collection
215 /// </summary>
216 /// <returns>The array</returns>
217 public T[] ToArray() { return collection.ToArray(); }
219 /// <summary>
220 /// Apply a delegate to all items of the wrapped enumerable.
221 /// </summary>
222 /// <param name="a">The delegate to apply</param>
223 //TODO: change this to throw an exception?
224 public void Apply(Applier<T> a) { collection.Apply(a); }
227 /// <summary>
228 /// Check if there exists an item that satisfies a
229 /// specific predicate in the wrapped enumerable.
230 /// </summary>
231 /// <param name="filter">A filter delegate
232 /// (<see cref="T:C5.Filter!1"/>) defining the predicate</param>
233 /// <returns>True is such an item exists</returns>
234 public bool Exists(Filter<T> filter) { return collection.Exists(filter); }
237 /// <summary>
238 /// Check if all items in the wrapped enumerable satisfies a specific predicate.
239 /// </summary>
240 /// <param name="filter">A filter delegate
241 /// (<see cref="T:C5.Filter!1"/>) defining the predicate</param>
242 /// <returns>True if all items satisfies the predicate</returns>
243 public bool All(Filter<T> filter) { return collection.All(filter); }
244 #endregion
249 /// <summary>
250 /// A read-only wrapper for a directed collection
252 /// <p>This is mainly interesting as a base of other guard classes</p>
253 /// </summary>
254 public class GuardedDirectedCollectionValue<T>: GuardedCollectionValue<T>, IDirectedCollectionValue<T>
256 #region Fields
258 IDirectedCollectionValue<T> directedcollection;
260 #endregion
262 #region Constructor
264 /// <summary>
265 /// Wrap a directed collection in a read-only wrapper
266 /// </summary>
267 /// <param name="directedcollection">the collection to wrap</param>
268 public GuardedDirectedCollectionValue(IDirectedCollectionValue<T> directedcollection) :
269 base(directedcollection)
270 { this.directedcollection = directedcollection; }
272 #endregion
274 #region IDirectedCollection<T> Members
276 /// <summary>
277 /// Get a collection that enumerates the wrapped collection in the opposite direction
278 /// </summary>
279 /// <returns>The mirrored collection</returns>
280 public IDirectedCollectionValue<T> Backwards()
281 { return new GuardedDirectedCollectionValue<T>(directedcollection.Backwards()); }
283 #endregion
285 #region IDirectedEnumerable<T> Members
287 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
288 { return Backwards(); }
291 /// <summary>
292 /// <code>Forwards</code> if same, else <code>Backwards</code>
293 /// </summary>
294 /// <value>The enumeration direction relative to the original collection.</value>
295 public EnumerationDirection Direction
296 { get { return directedcollection.Direction; } }
298 #endregion
303 /// <summary>
304 /// A read-only wrapper for an ICollection&lt;T&gt;.
305 /// <see cref="T:C5.ICollection!1"/>
307 /// <p>Suitable for wrapping hash tables, <see cref="T:C5.HashSet!1"/>
308 /// and <see cref="T:C5.HashBag!1"/> </p>
309 /// </summary>
310 public class GuardedCollection<T>: GuardedCollectionValue<T>, ICollection<T>
312 #region Fields
314 ICollection<T> collection;
316 #endregion
318 #region Constructor
320 /// <summary>
321 /// Wrap an ICollection&lt;T&gt; in a read-only wrapper
322 /// </summary>
323 /// <param name="collection">the collection to wrap</param>
324 public GuardedCollection(ICollection<T> collection)
325 :base(collection)
326 { this.collection = collection; }
328 #endregion
330 #region ICollection<T> Members
332 /// <summary>
333 /// (This is a read-only wrapper)
334 /// </summary>
335 /// <value>True</value>
336 public bool IsReadOnly { get { return true; } }
339 /// <summary> </summary>
340 /// <value>Speed of wrapped collection</value>
341 public Speed ContainsSpeed { get { return collection.ContainsSpeed; } }
344 int ICollection<T>.GetHashCode()
345 { return ((ICollection<T>)collection).GetHashCode(); }
348 bool ICollection<T>.Equals(ICollection<T> that)
349 { return ((ICollection<T>)collection).Equals(that); }
352 /// <summary>
353 /// Check if an item is in the wrapped collection
354 /// </summary>
355 /// <param name="item">The item</param>
356 /// <returns>True if found</returns>
357 public bool Contains(T item) { return collection.Contains(item); }
360 /// <summary>
361 /// Count the number of times an item appears in the wrapped collection
362 /// </summary>
363 /// <param name="item">The item</param>
364 /// <returns>The number of copies</returns>
365 public int ContainsCount(T item) { return collection.ContainsCount(item); }
368 /// <summary>
369 /// Check if all items in the argument is in the wrapped collection
370 /// </summary>
371 /// <param name="items">The items</param>
372 /// <returns>True if so</returns>
373 public bool ContainsAll(MSG.IEnumerable<T> items) { return collection.ContainsAll(items); }
376 /// <summary>
377 /// Search for an item in the wrapped collection
378 /// </summary>
379 /// <param name="item">On entry the item to look for, on exit the equivalent item found (if any)</param>
380 /// <returns></returns>
381 public bool Find(ref T item) { return collection.Find(ref item); }
384 /// <summary>
385 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
386 /// </summary>
387 /// <param name="item"></param>
388 /// <returns></returns>
389 public bool FindOrAdd(ref T item)
390 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
393 /// <summary>
394 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
395 /// </summary>
396 /// <param name="item"></param>
397 /// <returns></returns>
398 public bool Update(T item)
399 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
402 /// <summary>
403 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
404 /// </summary>
405 /// <param name="item"></param>
406 /// <returns></returns>
407 public bool UpdateOrAdd(T item)
408 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
411 /// <summary>
412 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
413 /// </summary>
414 /// <param name="item"></param>
415 /// <returns></returns>
416 public bool Remove(T item)
417 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
420 /// <summary>
421 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
422 /// </summary>
423 /// <param name="item"></param>
424 /// <returns></returns>
425 public bool RemoveWithReturn(ref T item)
426 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
429 /// <summary>
430 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
431 /// </summary>
432 /// <param name="item"></param>
433 public void RemoveAllCopies(T item)
434 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
437 /// <summary>
438 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
439 /// </summary>
440 /// <param name="items"></param>
441 public void RemoveAll(MSG.IEnumerable<T> items)
442 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
445 /// <summary>
446 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
447 /// </summary>
448 public void Clear()
449 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
452 /// <summary>
453 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
454 /// </summary>
455 /// <param name="items"></param>
456 public void RetainAll(MSG.IEnumerable<T> items)
457 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
460 /// <summary>
461 /// Check wrapped collection for internal consistency
462 /// </summary>
463 /// <returns>True if check passed</returns>
464 public bool Check() { return collection.Check(); }
466 #endregion
468 #region ISink<T> Members
470 /// <summary> </summary>
471 /// <value>False if wrapped collection has set semantics</value>
472 public bool AllowsDuplicates { get { return collection.AllowsDuplicates; } }
475 /// <summary> </summary>
476 /// <value>The sync root of the wrapped collection</value>
477 public object SyncRoot { get { return collection.SyncRoot; } }
480 /// <summary> </summary>
481 /// <value>True if wrapped collection is empty</value>
482 public bool IsEmpty { get { return collection.IsEmpty; } }
485 /// <summary>
486 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
487 /// </summary>
488 /// <param name="item"></param>
489 /// <returns></returns>
490 public bool Add(T item)
491 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
494 /// <summary>
495 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
496 /// </summary>
497 /// <param name="items"></param>
498 public void AddAll(MSG.IEnumerable<T> items)
499 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
501 /// <summary>
502 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
503 /// </summary>
504 /// <param name="items"></param>
505 /*public*/ void C5.IExtensible<T>.AddAll<U>(MSG.IEnumerable<U> items) //where U : T
506 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
508 #endregion
512 /// <summary>
513 /// A read-only wrapper for a sequenced collection
515 /// <p>This is mainly interesting as a base of other guard classes</p>
516 /// </summary>
517 public class GuardedSequenced<T>: GuardedCollection<T>, ISequenced<T>
519 #region Fields
521 ISequenced<T> sequenced;
523 #endregion
525 #region Constructor
527 /// <summary>
528 /// Wrap a sequenced collection in a read-only wrapper
529 /// </summary>
530 /// <param name="sorted"></param>
531 public GuardedSequenced(ISequenced<T> sorted):base(sorted) { this.sequenced = sorted; }
533 #endregion
535 #region ISequenced<T> Members
537 int ISequenced<T>.GetHashCode()
538 { return ((ISequenced<T>)sequenced).GetHashCode(); }
541 bool ISequenced<T>.Equals(ISequenced<T> that)
542 { return ((ISequenced<T>)sequenced).Equals(that); }
544 #endregion
546 #region IEditableCollection<T> Members
548 int ICollection<T>.GetHashCode()
549 { return ((ICollection<T>)sequenced).GetHashCode(); }
552 bool ICollection<T>.Equals(ICollection<T> that)
553 { return ((ICollection<T>)sequenced).Equals(that); }
555 #endregion
557 #region IDirectedCollection<T> Members
559 /// <summary>
560 /// Get a collection that enumerates the wrapped collection in the opposite direction
561 /// </summary>
562 /// <returns>The mirrored collection</returns>
563 public IDirectedCollectionValue<T> Backwards()
564 { return new GuardedDirectedCollectionValue<T>(sequenced.Backwards()); }
566 #endregion
568 #region IDirectedEnumerable<T> Members
570 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
571 { return Backwards(); }
575 /// <summary>
576 /// <code>Forwards</code> if same, else <code>Backwards</code>
577 /// </summary>
578 /// <value>The enumeration direction relative to the original collection.</value>
579 public EnumerationDirection Direction
580 { get { return EnumerationDirection.Forwards; } }
582 #endregion
587 /// <summary>
588 /// A read-only wrapper for a sorted collection
590 /// <p>This is mainly interesting as a base of other guard classes</p>
591 /// </summary>
592 public class GuardedSorted<T>: GuardedSequenced<T>, ISorted<T>
594 #region Fields
596 ISorted<T> sorted;
598 #endregion
600 #region Constructor
602 /// <summary>
603 /// Wrap a sorted collection in a read-only wrapper
604 /// </summary>
605 /// <param name="sorted"></param>
606 public GuardedSorted(ISorted<T> sorted):base(sorted) { this.sorted = sorted; }
608 #endregion
610 #region IEditableCollection Members
612 int ICollection<T>.GetHashCode()
613 { return ((ICollection<T>)sorted).GetHashCode(); }
616 bool ICollection<T>.Equals(ICollection<T> that)
617 { return ((ICollection<T>)sorted).Equals(that); }
619 #endregion
621 #region ISequenced<T> Members
623 int ISequenced<T>.GetHashCode()
624 { return ((ISequenced<T>)sorted).GetHashCode(); }
627 bool ISequenced<T>.Equals(ISequenced<T> that)
628 { return ((ISequenced<T>)sorted).Equals(that); }
631 #endregion
633 #region ISorted<T> Members
635 /// <summary>
636 /// Find the predecessor of the item in the wrapped sorted collection
637 /// </summary>
638 /// <param name="item">The item</param>
639 /// <returns>The predecessor</returns>
640 public T Predecessor(T item) { return sorted.Predecessor(item); }
643 /// <summary>
644 /// Find the Successor of the item in the wrapped sorted collection
645 /// </summary>
646 /// <param name="item">The item</param>
647 /// <returns>The Successor</returns>
648 public T Successor(T item) { return sorted.Successor(item); }
651 /// <summary>
652 /// Find the weak predecessor of the item in the wrapped sorted collection
653 /// </summary>
654 /// <param name="item">The item</param>
655 /// <returns>The weak predecessor</returns>
656 public T WeakPredecessor(T item) { return sorted.WeakPredecessor(item); }
659 /// <summary>
660 /// Find the weak Successor of the item in the wrapped sorted collection
661 /// </summary>
662 /// <param name="item">The item</param>
663 /// <returns>The weak Successor</returns>
664 public T WeakSuccessor(T item) { return sorted.WeakSuccessor(item); }
667 /// <summary>
668 /// Run Cut on the wrapped sorted collection
669 /// </summary>
670 /// <param name="c"></param>
671 /// <param name="low"></param>
672 /// <param name="lval"></param>
673 /// <param name="high"></param>
674 /// <param name="hval"></param>
675 /// <returns></returns>
676 public bool Cut(IComparable<T> c, out T low, out bool lval, out T high, out bool hval)
677 { return sorted.Cut(c, out low, out lval, out high, out hval); }
680 /// <summary>
681 /// Get the specified range from the wrapped collection.
682 /// (The current implementation erroneously does not wrap the result.)
683 /// </summary>
684 /// <param name="bot"></param>
685 /// <returns></returns>
686 public IDirectedEnumerable<T> RangeFrom(T bot) { return sorted.RangeFrom(bot); }
689 /// <summary>
690 /// Get the specified range from the wrapped collection.
691 /// (The current implementation erroneously does not wrap the result.)
692 /// </summary>
693 /// <param name="bot"></param>
694 /// <param name="top"></param>
695 /// <returns></returns>
696 public IDirectedEnumerable<T> RangeFromTo(T bot, T top)
697 { return sorted.RangeFromTo(bot, top); }
700 /// <summary>
701 /// Get the specified range from the wrapped collection.
702 /// (The current implementation erroneously does not wrap the result.)
703 /// </summary>
704 /// <param name="top"></param>
705 /// <returns></returns>
706 public IDirectedEnumerable<T> RangeTo(T top) { return sorted.RangeTo(top); }
709 /// <summary>
710 /// Get the specified range from the wrapped collection.
711 /// (The current implementation erroneously does not wrap the result.)
712 /// </summary>
713 /// <returns></returns>
714 public IDirectedCollectionValue<T> RangeAll() { return sorted.RangeAll(); }
717 /// <summary>
718 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
719 /// </summary>
720 /// <param name="items"></param>
721 public void AddSorted(MSG.IEnumerable<T> items)
722 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
725 /// <summary>
726 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
727 /// </summary>
728 /// <param name="low"></param>
729 public void RemoveRangeFrom(T low)
730 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
733 /// <summary>
734 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
735 /// </summary>
736 /// <param name="low"></param>
737 /// <param name="hi"></param>
738 public void RemoveRangeFromTo(T low, T hi)
739 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
742 /// <summary>
743 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
744 /// </summary>
745 /// <param name="hi"></param>
746 public void RemoveRangeTo(T hi)
747 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
749 #endregion
751 #region IPriorityQueue<T> Members
753 /// <summary>
754 /// Find the minimum of the wrapped collection
755 /// </summary>
756 /// <returns>The minimum</returns>
757 public T FindMin() { return sorted.FindMin(); }
760 /// <summary>
761 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
762 /// </summary>
763 /// <returns></returns>
764 public T DeleteMin()
765 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
768 /// <summary>
769 /// Find the maximum of the wrapped collection
770 /// </summary>
771 /// <returns>The maximum</returns>
772 public T FindMax() { return sorted.FindMax(); }
775 /// <summary>
776 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
777 /// </summary>
778 /// <returns></returns>
779 public T DeleteMax()
780 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
782 /// <summary>
783 /// The comparer object supplied at creation time for the underlying collection
784 /// </summary>
785 /// <value>The comparer</value>
786 public IComparer<T> Comparer { get { return sorted.Comparer; } }
787 #endregion
790 #region IDirectedEnumerable<T> Members
792 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
793 { return Backwards(); }
795 #endregion
800 /// <summary>
801 /// Read-only wrapper for indexed sorted collections
803 /// <p>Suitable for wrapping TreeSet, TreeBag and SortedArray</p>
804 /// </summary>
805 public class GuardedIndexedSorted<T>: GuardedSorted<T>, IIndexedSorted<T>
807 #region Fields
809 IIndexedSorted<T> indexedsorted;
811 #endregion
813 #region Constructor
815 /// <summary>
816 /// Wrap an indexed sorted collection in a read-only wrapper
817 /// </summary>
818 /// <param name="list">the indexed sorted collection</param>
819 public GuardedIndexedSorted(IIndexedSorted<T> list):base(list)
820 { this.indexedsorted = list; }
822 #endregion
824 #region IIndexedSorted<T> Members
826 /// <summary>
827 /// Get the specified range from the wrapped collection.
828 /// (The current implementation erroneously does not wrap the result.)
829 /// </summary>
830 /// <param name="bot"></param>
831 /// <returns></returns>
832 public new IDirectedCollectionValue<T> RangeFrom(T bot)
833 { return indexedsorted.RangeFrom(bot); }
836 /// <summary>
837 /// Get the specified range from the wrapped collection.
838 /// (The current implementation erroneously does not wrap the result.)
839 /// </summary>
840 /// <param name="bot"></param>
841 /// <param name="top"></param>
842 /// <returns></returns>
843 public new IDirectedCollectionValue<T> RangeFromTo(T bot, T top)
844 { return indexedsorted.RangeFromTo(bot, top); }
847 /// <summary>
848 /// Get the specified range from the wrapped collection.
849 /// (The current implementation erroneously does not wrap the result.)
850 /// </summary>
851 /// <param name="top"></param>
852 /// <returns></returns>
853 public new IDirectedCollectionValue<T> RangeTo(T top)
854 { return indexedsorted.RangeTo(top); }
857 /// <summary>
858 /// Report the number of items in the specified range of the wrapped collection
859 /// </summary>
860 /// <param name="bot"></param>
861 /// <returns></returns>
862 public int CountFrom(T bot) { return indexedsorted.CountFrom(bot); }
865 /// <summary>
866 /// Report the number of items in the specified range of the wrapped collection
867 /// </summary>
868 /// <param name="bot"></param>
869 /// <param name="top"></param>
870 /// <returns></returns>
871 public int CountFromTo(T bot, T top) { return indexedsorted.CountFromTo(bot, top); }
874 /// <summary>
875 /// Report the number of items in the specified range of the wrapped collection
876 /// </summary>
877 /// <param name="top"></param>
878 /// <returns></returns>
879 public int CountTo(T top) { return indexedsorted.CountTo(top); }
882 /// <summary>
883 /// Run FindAll on the wrapped collection with the indicated filter.
884 /// The result will <b>not</b> be read-only.
885 /// </summary>
886 /// <param name="f"></param>
887 /// <returns></returns>
888 public IIndexedSorted<T> FindAll(Filter<T> f)
889 { return indexedsorted.FindAll(f); }
892 /// <summary>
893 /// Run Map on the wrapped collection with the indicated mapper.
894 /// The result will <b>not</b> be read-only.
895 /// </summary>
896 /// <param name="m"></param>
897 /// <param name="c">The comparer to use in the result</param>
898 /// <returns></returns>
899 public IIndexedSorted<V> Map<V>(Mapper<T,V> m, IComparer<V> c)
900 { return indexedsorted.Map(m, c); }
902 #endregion
904 #region IIndexed<T> Members
906 /// <summary>
907 ///
908 /// </summary>
909 /// <value>The i'th item of the wrapped sorted collection</value>
910 public T this[int i] { get { return indexedsorted[i]; } }
913 /// <summary> </summary>
914 /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>
915 public IDirectedCollectionValue<T> this[int start, int end]
916 { get { return new GuardedDirectedCollectionValue<T>(indexedsorted[start, end]); } }
919 /// <summary>
920 /// Find the (first) index of an item in the wrapped collection
921 /// </summary>
922 /// <param name="item"></param>
923 /// <returns></returns>
924 public int IndexOf(T item) { return indexedsorted.IndexOf(item); }
927 /// <summary>
928 /// Find the last index of an item in the wrapped collection
929 /// </summary>
930 /// <param name="item"></param>
931 /// <returns></returns>
932 public int LastIndexOf(T item) { return indexedsorted.LastIndexOf(item); }
935 /// <summary>
936 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
937 /// </summary>
938 /// <param name="i"></param>
939 /// <returns></returns>
940 public T RemoveAt(int i)
941 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
944 /// <summary>
945 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
946 /// </summary>
947 /// <param name="start"></param>
948 /// <param name="count"></param>
949 public void RemoveInterval(int start, int count)
950 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
952 #endregion
954 #region ISequenced<T> Members
956 int ISequenced<T>.GetHashCode()
957 { return ((ISequenced<T>)indexedsorted).GetHashCode(); }
960 bool ISequenced<T>.Equals(ISequenced<T> that)
961 { return ((ISequenced<T>)indexedsorted).Equals(that); }
963 #endregion
965 #region IEditableCollection<T> Members
967 int ICollection<T>.GetHashCode()
968 { return ((ICollection<T>)indexedsorted).GetHashCode(); }
971 bool ICollection<T>.Equals(ICollection<T> that)
972 { return ((ICollection<T>)indexedsorted).Equals(that); }
974 #endregion
976 #region IDirectedEnumerable<T> Members
978 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
979 { return Backwards(); }
981 #endregion
986 /// <summary>
987 /// A read-only wrapper for a generic list collection
988 /// <p>Suitable as a wrapper for LinkedList, HashedLinkedList, ArrayList and HashedArray.
989 /// <see cref="T:C5.LinkedList!1"/>,
990 /// <see cref="T:C5.HashedLinkedList!1"/>,
991 /// <see cref="T:C5.ArrayList!1"/> or
992 /// <see cref="T:C5.HashedArray!1"/>.
993 /// </p>
994 /// </summary>
995 public class GuardedList<T>: GuardedSequenced<T>, IList<T>
997 #region Fields
999 IList<T> list;
1001 #endregion
1003 #region Constructor
1005 /// <summary>
1006 /// Wrap a list in a read-only wrapper
1007 /// </summary>
1008 /// <param name="list">The list</param>
1009 public GuardedList(IList<T> list) : base (list) { this.list = list; }
1011 #endregion
1013 #region IList<T> Members
1015 /// <summary>
1016 ///
1017 /// </summary>
1018 /// <value>The first item of the wrapped list</value>
1019 public T First { get { return list.First; } }
1022 /// <summary>
1023 ///
1024 /// </summary>
1025 /// <value>The last item of the wrapped list</value>
1026 public T Last { get { return list.Last; } }
1029 /// <summary>
1030 /// <exception cref="InvalidOperationException"/> if used as setter
1031 /// </summary>
1032 /// <value>True if wrapped list has FIFO semantics for the Add(T item) and Remove() methods</value>
1033 public bool FIFO
1035 get { return list.FIFO; }
1036 set { throw new InvalidOperationException("List is read only"); }
1040 /// <summary>
1041 /// <exception cref="InvalidOperationException"/> if used as setter
1042 /// </summary>
1043 /// <value>The i'th item of the wrapped list</value>
1044 public T this[int i]
1046 get { return list[i]; }
1047 set { throw new InvalidOperationException("List is read only"); }
1051 /// <summary>
1052 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1053 /// </summary>
1054 /// <param name="i"></param>
1055 /// <param name="item"></param>
1056 public void Insert(int i, T item)
1057 { throw new InvalidOperationException("List is read only"); }
1060 /// <summary>
1061 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1062 /// </summary>
1063 /// <param name="item"></param>
1064 public void InsertFirst(T item)
1065 { throw new InvalidOperationException("List is read only"); }
1067 /// <summary>
1068 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1069 /// </summary>
1070 /// <param name="item"></param>
1071 public void InsertLast(T item)
1072 { throw new InvalidOperationException("List is read only"); }
1074 /// <summary>
1075 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1076 /// </summary>
1077 /// <param name="item"></param>
1078 /// <param name="target"></param>
1079 public void InsertBefore(T item, T target)
1080 { throw new InvalidOperationException("List is read only"); }
1083 /// <summary>
1084 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1085 /// </summary>
1086 /// <param name="item"></param>
1087 /// <param name="target"></param>
1088 public void InsertAfter(T item, T target)
1089 { throw new InvalidOperationException("List is read only"); }
1092 /// <summary>
1093 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1094 /// </summary>
1095 /// <param name="i"></param>
1096 /// <param name="items"></param>
1097 public void InsertAll(int i, MSG.IEnumerable<T> items)
1098 { throw new InvalidOperationException("List is read only"); }
1101 /// <summary>
1102 /// Perform FindAll on the wrapped list. The result is <b>not</b> necessarily read-only.
1103 /// </summary>
1104 /// <param name="filter">The filter to use</param>
1105 /// <returns></returns>
1106 public IList<T> FindAll(Filter<T> filter) { return list.FindAll(filter); }
1109 /// <summary>
1110 /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
1111 /// </summary>
1112 /// <typeparam name="V">The type of items of the new list</typeparam>
1113 /// <param name="mapper">The mapper to use.</param>
1114 /// <returns>The mapped list</returns>
1115 public IList<V> Map<V>(Mapper<T, V> mapper) { return list.Map(mapper); }
1117 /// <summary>
1118 /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
1119 /// </summary>
1120 /// <typeparam name="V">The type of items of the new list</typeparam>
1121 /// <param name="mapper">The delegate defining the map.</param>
1122 /// <param name="hasher">The hasher to use for the new list</param>
1123 /// <returns>The new list.</returns>
1124 public IList<V> Map<V>(Mapper<T, V> mapper, IHasher<V> hasher) { return list.Map(mapper, hasher); }
1126 /// <summary>
1127 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1128 /// </summary>
1129 /// <returns></returns>
1130 public T Remove() { throw new InvalidOperationException("List is read only"); }
1133 /// <summary>
1134 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1135 /// </summary>
1136 /// <returns></returns>
1137 public T RemoveFirst() { throw new InvalidOperationException("List is read only"); }
1140 /// <summary>
1141 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1142 /// </summary>
1143 /// <returns></returns>
1144 public T RemoveLast() { throw new InvalidOperationException("List is read only"); }
1147 /// <summary>
1148 /// Create the indicated view on the wrapped list and wrap it read-only.
1149 /// </summary>
1150 /// <param name="start"></param>
1151 /// <param name="count"></param>
1152 /// <returns></returns>
1153 public IList<T> View(int start, int count)
1155 return new GuardedList<T>(list.View(start, count));
1159 //TODO: This is wrong!
1160 /// <summary>
1161 /// (This is wrong functionality)
1162 /// </summary>
1163 /// <value>The wrapped underlying list of the wrapped view </value>
1164 public IList<T> Underlying { get { return new GuardedList<T>(list.Underlying); } }
1167 /// <summary>
1168 ///
1169 /// </summary>
1170 /// <value>The offset of the wrapped list as a view.</value>
1171 public int Offset { get { return list.Offset; } }
1174 /// <summary>
1175 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1176 /// </summary>
1177 /// <param name="offset"></param>
1178 public void Slide(int offset) { throw new InvalidOperationException("List is read only"); }
1181 /// <summary>
1182 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1183 /// </summary>
1184 /// <param name="offset"></param>
1185 /// <param name="size"></param>
1186 public void Slide(int offset, int size) { throw new InvalidOperationException("List is read only"); }
1189 /// <summary>
1190 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1191 /// </summary>
1192 public void Reverse() { throw new InvalidOperationException("List is read only"); }
1195 /// <summary>
1196 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1197 /// </summary>
1198 /// <param name="start"></param>
1199 /// <param name="count"></param>
1200 public void Reverse(int start, int count)
1201 { throw new InvalidOperationException("List is read only"); }
1204 /// <summary>
1205 /// Check if wrapped list is sorted
1206 /// </summary>
1207 /// <param name="c">The sorting order to use</param>
1208 /// <returns>True if sorted</returns>
1209 public bool IsSorted(IComparer<T> c) { return list.IsSorted(c); }
1212 /// <summary>
1213 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1214 /// </summary>
1215 /// <param name="c"></param>
1216 public void Sort(IComparer<T> c)
1217 { throw new InvalidOperationException("List is read only"); }
1220 /// <summary>
1221 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1222 /// </summary>
1223 public void Shuffle()
1224 { throw new InvalidOperationException("List is read only"); }
1227 /// <summary>
1228 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1229 /// </summary>
1230 /// <param name="rnd"></param>
1231 public void Shuffle(Random rnd)
1232 { throw new InvalidOperationException("List is read only"); }
1234 #endregion
1236 #region IIndexed<T> Members
1238 /// <summary> </summary>
1239 /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>
1240 public IDirectedCollectionValue<T> this[int start, int end]
1241 { get { return new GuardedDirectedCollectionValue<T>(list[start, end]); } }
1244 /// <summary>
1245 /// Find the (first) index of an item in the wrapped collection
1246 /// </summary>
1247 /// <param name="item"></param>
1248 /// <returns></returns>
1249 public int IndexOf(T item) { return list.IndexOf(item); }
1252 /// <summary>
1253 /// Find the last index of an item in the wrapped collection
1254 /// </summary>
1255 /// <param name="item"></param>
1256 /// <returns></returns>
1257 public int LastIndexOf(T item) { return list.LastIndexOf(item); }
1260 /// <summary>
1261 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1262 /// </summary>
1263 /// <param name="i"></param>
1264 /// <returns></returns>
1265 public T RemoveAt(int i)
1266 { throw new InvalidOperationException("List is read only"); }
1269 /// <summary>
1270 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1271 /// </summary>
1272 /// <param name="start"></param>
1273 /// <param name="count"></param>
1274 public void RemoveInterval(int start, int count)
1275 { throw new InvalidOperationException("List is read only"); }
1277 #endregion
1279 #region ISequenced<T> Members
1281 int ISequenced<T>.GetHashCode()
1282 { return ((ISequenced<T>)list).GetHashCode(); }
1285 bool ISequenced<T>.Equals(ISequenced<T> that)
1286 { return ((ISequenced<T>)list).Equals(that); }
1288 #endregion
1290 #region IEditableCollection<T> Members
1292 int ICollection<T>.GetHashCode()
1293 { return ((ICollection<T>)list).GetHashCode(); }
1296 bool ICollection<T>.Equals(ICollection<T> that)
1297 { return ((ICollection<T>)list).Equals(that); }
1299 #endregion
1301 #region IDirectedEnumerable<T> Members
1303 IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
1304 { return Backwards(); }
1306 #endregion
1308 #region IStack<T> Members
1311 /// <summary>
1312 ///
1313 /// </summary>
1314 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1315 /// <returns>-</returns>
1316 public void Push(T item)
1317 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
1319 /// <summary>
1320 ///
1321 /// </summary>
1322 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1323 /// <returns>-</returns>
1324 public T Pop()
1325 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
1327 #endregion
1329 #region IQueue<T> Members
1331 /// <summary>
1332 ///
1333 /// </summary>
1334 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1335 /// <returns>-</returns>
1336 public void EnQueue(T item)
1337 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
1339 /// <summary>
1340 ///
1341 /// </summary>
1342 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1343 /// <returns>-</returns>
1344 public T DeQueue()
1345 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
1347 #endregion
1353 /// <summary>
1354 /// A read-only wrapper for a dictionary.
1356 /// <p>Suitable for wrapping a HashDictionary. <see cref="T:C5.HashDictionary!2"/></p>
1357 /// </summary>
1358 public class GuardedDictionary<K,V>: GuardedEnumerable<KeyValuePair<K,V>>, IDictionary<K,V>
1360 #region Fields
1362 IDictionary<K,V> dict;
1364 #endregion
1366 #region Constructor
1368 /// <summary>
1369 /// Wrap a dictionary in a read-only wrapper
1370 /// </summary>
1371 /// <param name="dict">the dictionary</param>
1372 public GuardedDictionary(IDictionary<K,V> dict) : base(dict) { this.dict = dict; }
1374 #endregion
1376 #region IDictionary<K,V> Members
1378 /// <summary>
1379 /// <exception cref="InvalidOperationException"/> since this is a
1380 /// read-only wrappper if used as a setter
1381 /// </summary>
1382 /// <value>Get the value corresponding to a key in the wrapped dictionary</value>
1383 public V this[K key]
1385 get { return dict[key]; }
1386 set { throw new InvalidOperationException("Dictionary is read only"); }
1390 /// <summary> </summary>
1391 /// <value>The size of the wrapped dictionary</value>
1392 public int Count { get { return dict.Count; } }
1395 /// <summary>
1396 /// (This is a read-only wrapper)
1397 /// </summary>
1398 /// <value>True</value>
1399 public bool IsReadOnly { get { return true; } }
1402 /// <summary> </summary>
1403 /// <value>The sync root of the wrapped dictionary</value>
1404 public object SyncRoot { get { return dict.SyncRoot; } }
1407 //TODO: guard with a read-only wrapper? Probably so!
1408 /// <summary> </summary>
1409 /// <value>The collection of keys of the wrapped dictionary</value>
1410 public ICollectionValue<K> Keys
1411 { get { return dict.Keys; } }
1414 /// <summary> </summary>
1415 /// <value>The collection of values of the wrapped dictionary</value>
1416 public ICollectionValue<V> Values { get { return dict.Values; } }
1419 /// <summary>
1420 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1421 /// </summary>
1422 /// <param name="key"></param>
1423 /// <param name="val"></param>
1424 public void Add(K key, V val)
1425 { throw new InvalidOperationException("Dictionary is read only"); }
1428 /// <summary>
1429 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1430 /// </summary>
1431 /// <param name="key"></param>
1432 /// <returns></returns>
1433 public bool Remove(K key)
1434 { throw new InvalidOperationException("Dictionary is read only"); }
1437 /// <summary>
1438 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1439 /// </summary>
1440 /// <param name="key"></param>
1441 /// <param name="val"></param>
1442 /// <returns></returns>
1443 public bool Remove(K key, out V val)
1444 { throw new InvalidOperationException("Dictionary is read only"); }
1447 /// <summary>
1448 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1449 /// </summary>
1450 public void Clear()
1451 { throw new InvalidOperationException("Dictionary is read only"); }
1454 /// <summary>
1455 /// Check if the wrapped dictionary contains a specific key
1456 /// </summary>
1457 /// <param name="key">The key</param>
1458 /// <returns>True if it does</returns>
1459 public bool Contains(K key) { return dict.Contains(key); }
1462 /// <summary>
1463 /// Search for a key in the wrapped dictionary, reporting the value if found
1464 /// </summary>
1465 /// <param name="key">The key</param>
1466 /// <param name="val">On exit: the value if found</param>
1467 /// <returns>True if found</returns>
1468 public bool Find(K key, out V val) { return dict.Find(key, out val); }
1471 /// <summary>
1472 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1473 /// </summary>
1474 /// <param name="key"></param>
1475 /// <param name="val"></param>
1476 /// <returns></returns>
1477 public bool Update(K key, V val)
1478 { throw new InvalidOperationException("Dictionary is read only"); }
1481 /// <summary>
1482 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1483 /// </summary>
1484 /// <param name="key"></param>
1485 /// <param name="val"></param>
1486 /// <returns></returns>
1487 public bool FindOrAdd(K key, ref V val)
1488 { throw new InvalidOperationException("Dictionary is read only"); }
1491 /// <summary>
1492 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1493 /// </summary>
1494 /// <param name="key"></param>
1495 /// <param name="val"></param>
1496 /// <returns></returns>
1497 public bool UpdateOrAdd(K key, V val)
1498 { throw new InvalidOperationException("Dictionary is read only"); }
1501 /// <summary>
1502 /// Check the internal consistency of the wrapped dictionary
1503 /// </summary>
1504 /// <returns>True if check passed</returns>
1505 public bool Check() { return dict.Check(); }
1507 #endregion
1512 /// <summary>
1513 /// A read-only wrapper for a sorted dictionary.
1515 /// <p>Suitable for wrapping a Dictionary. <see cref="T:C5.Dictionary!2"/></p>
1516 /// </summary>
1517 public class GuardedSortedDictionary<K,V>: GuardedDictionary<K,V>, ISortedDictionary<K,V>
1519 #region Fields
1521 ISortedDictionary<K,V> sorteddict;
1523 #endregion
1525 #region Constructor
1527 /// <summary>
1528 /// Wrap a sorted dictionary in a read-only wrapper
1529 /// </summary>
1530 /// <param name="sorteddict">the dictionary</param>
1531 public GuardedSortedDictionary(ISortedDictionary<K,V> sorteddict) :base(sorteddict)
1532 { this.sorteddict = sorteddict; }
1534 #endregion
1536 #region ISortedDictionary<K,V> Members
1538 /// <summary>
1539 /// Get the entry in the wrapped dictionary whose key is the
1540 /// predecessor of a specified key.
1541 /// </summary>
1542 /// <param name="key">The key</param>
1543 /// <returns>The entry</returns>
1544 public KeyValuePair<K,V> Predecessor(K key)
1545 { return sorteddict.Predecessor(key); }
1548 /// <summary>
1549 /// Get the entry in the wrapped dictionary whose key is the
1550 /// successor of a specified key.
1551 /// </summary>
1552 /// <param name="key">The key</param>
1553 /// <returns>The entry</returns>
1554 public KeyValuePair<K,V> Successor(K key)
1555 { return sorteddict.Successor(key); }
1558 /// <summary>
1559 /// Get the entry in the wrapped dictionary whose key is the
1560 /// weak predecessor of a specified key.
1561 /// </summary>
1562 /// <param name="key">The key</param>
1563 /// <returns>The entry</returns>
1564 public KeyValuePair<K,V> WeakPredecessor(K key)
1565 { return sorteddict.WeakPredecessor(key); }
1568 /// <summary>
1569 /// Get the entry in the wrapped dictionary whose key is the
1570 /// weak successor of a specified key.
1571 /// </summary>
1572 /// <param name="key">The key</param>
1573 /// <returns>The entry</returns>
1574 public KeyValuePair<K,V> WeakSuccessor(K key)
1575 { return sorteddict.WeakSuccessor(key); }
1577 #endregion
1581 #endif