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
24 using System
.Diagnostics
;
25 using MSG
= System
.Collections
.Generic
;
29 /// A read-only wrapper class for a generic enumerator
31 public class GuardedEnumerator
<T
>: MSG
.IEnumerator
<T
>
35 MSG
.IEnumerator
<T
> enumerator
;
42 /// Create a wrapper around a generic enumerator
44 /// <param name="enumerator">The enumerator to wrap</param>
45 public GuardedEnumerator(MSG
.IEnumerator
<T
> enumerator
)
46 { this.enumerator = enumerator; }
50 #region IEnumerator<T> Members
53 /// Move wrapped enumerator to next item, or the first item if
54 /// this is the first call to MoveNext.
56 /// <returns>True if enumerator is valid now</returns>
57 public bool MoveNext() { return enumerator.MoveNext(); }
61 /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
63 /// <value>The current item of the wrapped enumerator.</value>
64 public T Current { get { return enumerator.Current; }
}
68 #region IDisposable Members
71 /// Dispose wrapped enumerator
73 public void Dispose() { enumerator.Dispose(); }
81 /// A read-only wrapper class for a generic enumerable
83 /// <p>This is mainly interesting as a base of other guard classes</p>
85 public class GuardedEnumerable
<T
>: MSG
.IEnumerable
<T
>
89 MSG
.IEnumerable
<T
> enumerable
;
96 /// Wrap an enumerable in a read-only wrapper
98 /// <param name="enumerable">The enumerable to wrap</param>
99 public GuardedEnumerable(MSG
.IEnumerable
<T
> enumerable
)
100 { this.enumerable = enumerable; }
104 #region MSG.IEnumerable<T> Members
107 /// Get an enumerator from the wrapped enumerable
109 /// <returns>The enumerator (itself wrapped)</returns>
110 public MSG
.IEnumerator
<T
> GetEnumerator()
111 { return new GuardedEnumerator<T>(enumerable.GetEnumerator()); }
119 /// A read-only wrapper for a generic directed enumerable
121 /// <p>This is mainly interesting as a base of other guard classes</p>
123 public class GuardedDirectedEnumerable
<T
>: GuardedEnumerable
<T
>, IDirectedEnumerable
<T
>
127 IDirectedEnumerable
<T
> directedenumerable
;
134 /// Wrap a directed enumerable in a read-only wrapper
136 /// <param name="directedenumerable">the collection to wrap</param>
137 public GuardedDirectedEnumerable(IDirectedEnumerable
<T
> directedenumerable
)
138 : base(directedenumerable
)
139 { this.directedenumerable = directedenumerable; }
143 #region IDirectedEnumerable<T> Members
146 /// Get a enumerable that enumerates the wrapped collection in the opposite direction
148 /// <returns>The mirrored enumerable</returns>
149 public IDirectedEnumerable
<T
> Backwards()
150 { return new GuardedDirectedEnumerable<T>(directedenumerable.Backwards()); }
154 /// <code>Forwards</code> if same, else <code>Backwards</code>
156 /// <value>The enumeration direction relative to the original collection.</value>
157 public EnumerationDirection Direction
158 { get { return directedenumerable.Direction; }
}
166 /// A read-only wrapper for an ICollectionValue<T>
168 /// <p>This is mainly interesting as a base of other guard classes</p>
170 public class GuardedCollectionValue
<T
>: GuardedEnumerable
<T
>, ICollectionValue
<T
>
174 ICollectionValue
<T
> collection
;
181 /// Wrap a ICollectionValue<T> in a read-only wrapper
183 /// <param name="collection">the collection to wrap</param>
184 public GuardedCollectionValue(ICollectionValue
<T
> collection
) : base(collection
)
185 { this.collection = collection; }
189 #region ICollection<T> Members
192 /// Get the size of the wrapped collection
194 /// <value>The size</value>
195 public int Count { get { return collection.Count; }
}
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
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; }
}
207 /// Copy the items of the wrapped collection to an array
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); }
214 /// Create an array from the items of the wrapped collection
216 /// <returns>The array</returns>
217 public T
[] ToArray() { return collection.ToArray(); }
220 /// Apply a delegate to all items of the wrapped enumerable.
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); }
228 /// Check if there exists an item that satisfies a
229 /// specific predicate in the wrapped enumerable.
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); }
238 /// Check if all items in the wrapped enumerable satisfies a specific predicate.
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); }
250 /// A read-only wrapper for a directed collection
252 /// <p>This is mainly interesting as a base of other guard classes</p>
254 public class GuardedDirectedCollectionValue
<T
>: GuardedCollectionValue
<T
>, IDirectedCollectionValue
<T
>
258 IDirectedCollectionValue
<T
> directedcollection
;
265 /// Wrap a directed collection in a read-only wrapper
267 /// <param name="directedcollection">the collection to wrap</param>
268 public GuardedDirectedCollectionValue(IDirectedCollectionValue
<T
> directedcollection
) :
269 base(directedcollection
)
270 { this.directedcollection = directedcollection; }
274 #region IDirectedCollection<T> Members
277 /// Get a collection that enumerates the wrapped collection in the opposite direction
279 /// <returns>The mirrored collection</returns>
280 public IDirectedCollectionValue
<T
> Backwards()
281 { return new GuardedDirectedCollectionValue<T>(directedcollection.Backwards()); }
285 #region IDirectedEnumerable<T> Members
287 IDirectedEnumerable
<T
> IDirectedEnumerable
<T
>.Backwards()
288 { return Backwards(); }
292 /// <code>Forwards</code> if same, else <code>Backwards</code>
294 /// <value>The enumeration direction relative to the original collection.</value>
295 public EnumerationDirection Direction
296 { get { return directedcollection.Direction; }
}
304 /// A read-only wrapper for an ICollection<T>.
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>
310 public class GuardedCollection
<T
>: GuardedCollectionValue
<T
>, ICollection
<T
>
314 ICollection
<T
> collection
;
321 /// Wrap an ICollection<T> in a read-only wrapper
323 /// <param name="collection">the collection to wrap</param>
324 public GuardedCollection(ICollection
<T
> collection
)
326 { this.collection = collection; }
330 #region ICollection<T> Members
333 /// (This is a read-only wrapper)
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); }
353 /// Check if an item is in the wrapped collection
355 /// <param name="item">The item</param>
356 /// <returns>True if found</returns>
357 public bool Contains(T item
) { return collection.Contains(item); }
361 /// Count the number of times an item appears in the wrapped collection
363 /// <param name="item">The item</param>
364 /// <returns>The number of copies</returns>
365 public int ContainsCount(T item
) { return collection.ContainsCount(item); }
369 /// Check if all items in the argument is in the wrapped collection
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); }
377 /// Search for an item in the wrapped collection
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); }
385 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
394 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
403 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
412 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
421 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
430 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
432 /// <param name="item"></param>
433 public void RemoveAllCopies(T item
)
434 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
438 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
446 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
449 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
453 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
461 /// Check wrapped collection for internal consistency
463 /// <returns>True if check passed</returns>
464 public bool Check() { return collection.Check(); }
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; }
}
486 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
495 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
502 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
513 /// A read-only wrapper for a sequenced collection
515 /// <p>This is mainly interesting as a base of other guard classes</p>
517 public class GuardedSequenced
<T
>: GuardedCollection
<T
>, ISequenced
<T
>
521 ISequenced
<T
> sequenced
;
528 /// Wrap a sequenced collection in a read-only wrapper
530 /// <param name="sorted"></param>
531 public GuardedSequenced(ISequenced
<T
> sorted
):base(sorted
) { this.sequenced = sorted; }
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); }
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); }
557 #region IDirectedCollection<T> Members
560 /// Get a collection that enumerates the wrapped collection in the opposite direction
562 /// <returns>The mirrored collection</returns>
563 public IDirectedCollectionValue
<T
> Backwards()
564 { return new GuardedDirectedCollectionValue<T>(sequenced.Backwards()); }
568 #region IDirectedEnumerable<T> Members
570 IDirectedEnumerable
<T
> IDirectedEnumerable
<T
>.Backwards()
571 { return Backwards(); }
576 /// <code>Forwards</code> if same, else <code>Backwards</code>
578 /// <value>The enumeration direction relative to the original collection.</value>
579 public EnumerationDirection Direction
580 { get { return EnumerationDirection.Forwards; }
}
588 /// A read-only wrapper for a sorted collection
590 /// <p>This is mainly interesting as a base of other guard classes</p>
592 public class GuardedSorted
<T
>: GuardedSequenced
<T
>, ISorted
<T
>
603 /// Wrap a sorted collection in a read-only wrapper
605 /// <param name="sorted"></param>
606 public GuardedSorted(ISorted
<T
> sorted
):base(sorted
) { this.sorted = sorted; }
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); }
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); }
633 #region ISorted<T> Members
636 /// Find the predecessor of the item in the wrapped sorted collection
638 /// <param name="item">The item</param>
639 /// <returns>The predecessor</returns>
640 public T
Predecessor(T item
) { return sorted.Predecessor(item); }
644 /// Find the Successor of the item in the wrapped sorted collection
646 /// <param name="item">The item</param>
647 /// <returns>The Successor</returns>
648 public T
Successor(T item
) { return sorted.Successor(item); }
652 /// Find the weak predecessor of the item in the wrapped sorted collection
654 /// <param name="item">The item</param>
655 /// <returns>The weak predecessor</returns>
656 public T
WeakPredecessor(T item
) { return sorted.WeakPredecessor(item); }
660 /// Find the weak Successor of the item in the wrapped sorted collection
662 /// <param name="item">The item</param>
663 /// <returns>The weak Successor</returns>
664 public T
WeakSuccessor(T item
) { return sorted.WeakSuccessor(item); }
668 /// Run Cut on the wrapped sorted collection
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); }
681 /// Get the specified range from the wrapped collection.
682 /// (The current implementation erroneously does not wrap the result.)
684 /// <param name="bot"></param>
685 /// <returns></returns>
686 public IDirectedEnumerable
<T
> RangeFrom(T bot
) { return sorted.RangeFrom(bot); }
690 /// Get the specified range from the wrapped collection.
691 /// (The current implementation erroneously does not wrap the result.)
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); }
701 /// Get the specified range from the wrapped collection.
702 /// (The current implementation erroneously does not wrap the result.)
704 /// <param name="top"></param>
705 /// <returns></returns>
706 public IDirectedEnumerable
<T
> RangeTo(T top
) { return sorted.RangeTo(top); }
710 /// Get the specified range from the wrapped collection.
711 /// (The current implementation erroneously does not wrap the result.)
713 /// <returns></returns>
714 public IDirectedCollectionValue
<T
> RangeAll() { return sorted.RangeAll(); }
718 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
726 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
728 /// <param name="low"></param>
729 public void RemoveRangeFrom(T low
)
730 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
734 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
743 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
745 /// <param name="hi"></param>
746 public void RemoveRangeTo(T hi
)
747 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
751 #region IPriorityQueue<T> Members
754 /// Find the minimum of the wrapped collection
756 /// <returns>The minimum</returns>
757 public T
FindMin() { return sorted.FindMin(); }
761 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
763 /// <returns></returns>
765 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
769 /// Find the maximum of the wrapped collection
771 /// <returns>The maximum</returns>
772 public T
FindMax() { return sorted.FindMax(); }
776 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
778 /// <returns></returns>
780 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
783 /// The comparer object supplied at creation time for the underlying collection
785 /// <value>The comparer</value>
786 public IComparer
<T
> Comparer { get { return sorted.Comparer; }
}
790 #region IDirectedEnumerable<T> Members
792 IDirectedEnumerable
<T
> IDirectedEnumerable
<T
>.Backwards()
793 { return Backwards(); }
801 /// Read-only wrapper for indexed sorted collections
803 /// <p>Suitable for wrapping TreeSet, TreeBag and SortedArray</p>
805 public class GuardedIndexedSorted
<T
>: GuardedSorted
<T
>, IIndexedSorted
<T
>
809 IIndexedSorted
<T
> indexedsorted
;
816 /// Wrap an indexed sorted collection in a read-only wrapper
818 /// <param name="list">the indexed sorted collection</param>
819 public GuardedIndexedSorted(IIndexedSorted
<T
> list
):base(list
)
820 { this.indexedsorted = list; }
824 #region IIndexedSorted<T> Members
827 /// Get the specified range from the wrapped collection.
828 /// (The current implementation erroneously does not wrap the result.)
830 /// <param name="bot"></param>
831 /// <returns></returns>
832 public new IDirectedCollectionValue
<T
> RangeFrom(T bot
)
833 { return indexedsorted.RangeFrom(bot); }
837 /// Get the specified range from the wrapped collection.
838 /// (The current implementation erroneously does not wrap the result.)
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); }
848 /// Get the specified range from the wrapped collection.
849 /// (The current implementation erroneously does not wrap the result.)
851 /// <param name="top"></param>
852 /// <returns></returns>
853 public new IDirectedCollectionValue
<T
> RangeTo(T top
)
854 { return indexedsorted.RangeTo(top); }
858 /// Report the number of items in the specified range of the wrapped collection
860 /// <param name="bot"></param>
861 /// <returns></returns>
862 public int CountFrom(T bot
) { return indexedsorted.CountFrom(bot); }
866 /// Report the number of items in the specified range of the wrapped collection
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); }
875 /// Report the number of items in the specified range of the wrapped collection
877 /// <param name="top"></param>
878 /// <returns></returns>
879 public int CountTo(T top
) { return indexedsorted.CountTo(top); }
883 /// Run FindAll on the wrapped collection with the indicated filter.
884 /// The result will <b>not</b> be read-only.
886 /// <param name="f"></param>
887 /// <returns></returns>
888 public IIndexedSorted
<T
> FindAll(Filter
<T
> f
)
889 { return indexedsorted.FindAll(f); }
893 /// Run Map on the wrapped collection with the indicated mapper.
894 /// The result will <b>not</b> be read-only.
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); }
904 #region IIndexed<T> Members
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]); }
}
920 /// Find the (first) index of an item in the wrapped collection
922 /// <param name="item"></param>
923 /// <returns></returns>
924 public int IndexOf(T item
) { return indexedsorted.IndexOf(item); }
928 /// Find the last index of an item in the wrapped collection
930 /// <param name="item"></param>
931 /// <returns></returns>
932 public int LastIndexOf(T item
) { return indexedsorted.LastIndexOf(item); }
936 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
945 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
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); }
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); }
976 #region IDirectedEnumerable<T> Members
978 IDirectedEnumerable
<T
> IDirectedEnumerable
<T
>.Backwards()
979 { return Backwards(); }
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"/>.
995 public class GuardedList
<T
>: GuardedSequenced
<T
>, IList
<T
>
1006 /// Wrap a list in a read-only wrapper
1008 /// <param name="list">The list</param>
1009 public GuardedList(IList
<T
> list
) : base (list
) { this.list = list; }
1013 #region IList<T> Members
1018 /// <value>The first item of the wrapped list</value>
1019 public T First { get { return list.First; }
}
1025 /// <value>The last item of the wrapped list</value>
1026 public T Last { get { return list.Last; }
}
1030 /// <exception cref="InvalidOperationException"/> if used as setter
1032 /// <value>True if wrapped list has FIFO semantics for the Add(T item) and Remove() methods</value>
1035 get { return list.FIFO; }
1036 set { throw new InvalidOperationException("List is read only"); }
1041 /// <exception cref="InvalidOperationException"/> if used as setter
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"); }
1052 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
1061 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1063 /// <param name="item"></param>
1064 public void InsertFirst(T item
)
1065 { throw new InvalidOperationException("List is read only"); }
1068 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1070 /// <param name="item"></param>
1071 public void InsertLast(T item
)
1072 { throw new InvalidOperationException("List is read only"); }
1075 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
1084 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
1093 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
1102 /// Perform FindAll on the wrapped list. The result is <b>not</b> necessarily read-only.
1104 /// <param name="filter">The filter to use</param>
1105 /// <returns></returns>
1106 public IList
<T
> FindAll(Filter
<T
> filter
) { return list.FindAll(filter); }
1110 /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
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); }
1118 /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
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); }
1127 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1129 /// <returns></returns>
1130 public T
Remove() { throw new InvalidOperationException("List is read only"); }
1134 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1136 /// <returns></returns>
1137 public T
RemoveFirst() { throw new InvalidOperationException("List is read only"); }
1141 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1143 /// <returns></returns>
1144 public T
RemoveLast() { throw new InvalidOperationException("List is read only"); }
1148 /// Create the indicated view on the wrapped list and wrap it read-only.
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!
1161 /// (This is wrong functionality)
1163 /// <value>The wrapped underlying list of the wrapped view </value>
1164 public IList
<T
> Underlying { get { return new GuardedList<T>(list.Underlying); }
}
1170 /// <value>The offset of the wrapped list as a view.</value>
1171 public int Offset { get { return list.Offset; }
}
1175 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1177 /// <param name="offset"></param>
1178 public void Slide(int offset
) { throw new InvalidOperationException("List is read only"); }
1182 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
1190 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1192 public void Reverse() { throw new InvalidOperationException("List is read only"); }
1196 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
1205 /// Check if wrapped list is sorted
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); }
1213 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1215 /// <param name="c"></param>
1216 public void Sort(IComparer
<T
> c
)
1217 { throw new InvalidOperationException("List is read only"); }
1221 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1223 public void Shuffle()
1224 { throw new InvalidOperationException("List is read only"); }
1228 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1230 /// <param name="rnd"></param>
1231 public void Shuffle(Random rnd
)
1232 { throw new InvalidOperationException("List is read only"); }
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]); }
}
1245 /// Find the (first) index of an item in the wrapped collection
1247 /// <param name="item"></param>
1248 /// <returns></returns>
1249 public int IndexOf(T item
) { return list.IndexOf(item); }
1253 /// Find the last index of an item in the wrapped collection
1255 /// <param name="item"></param>
1256 /// <returns></returns>
1257 public int LastIndexOf(T item
) { return list.LastIndexOf(item); }
1261 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1263 /// <param name="i"></param>
1264 /// <returns></returns>
1265 public T
RemoveAt(int i
)
1266 { throw new InvalidOperationException("List is read only"); }
1270 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
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); }
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); }
1301 #region IDirectedEnumerable<T> Members
1303 IDirectedEnumerable
<T
> IDirectedEnumerable
<T
>.Backwards()
1304 { return Backwards(); }
1308 #region IStack<T> Members
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"); }
1322 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1323 /// <returns>-</returns>
1325 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
1329 #region IQueue<T> Members
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"); }
1342 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1343 /// <returns>-</returns>
1345 { throw new InvalidOperationException("Collection cannot be modified through this guard object"); }
1354 /// A read-only wrapper for a dictionary.
1356 /// <p>Suitable for wrapping a HashDictionary. <see cref="T:C5.HashDictionary!2"/></p>
1358 public class GuardedDictionary
<K
,V
>: GuardedEnumerable
<KeyValuePair
<K
,V
>>, IDictionary
<K
,V
>
1362 IDictionary
<K
,V
> dict
;
1369 /// Wrap a dictionary in a read-only wrapper
1371 /// <param name="dict">the dictionary</param>
1372 public GuardedDictionary(IDictionary
<K
,V
> dict
) : base(dict
) { this.dict = dict; }
1376 #region IDictionary<K,V> Members
1379 /// <exception cref="InvalidOperationException"/> since this is a
1380 /// read-only wrappper if used as a setter
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; }
}
1396 /// (This is a read-only wrapper)
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; }
}
1420 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
1429 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1431 /// <param name="key"></param>
1432 /// <returns></returns>
1433 public bool Remove(K key
)
1434 { throw new InvalidOperationException("Dictionary is read only"); }
1438 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
1448 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
1451 { throw new InvalidOperationException("Dictionary is read only"); }
1455 /// Check if the wrapped dictionary contains a specific key
1457 /// <param name="key">The key</param>
1458 /// <returns>True if it does</returns>
1459 public bool Contains(K key
) { return dict.Contains(key); }
1463 /// Search for a key in the wrapped dictionary, reporting the value if found
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); }
1472 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
1482 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
1492 /// <exception cref="InvalidOperationException"/> since this is a read-only wrappper
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"); }
1502 /// Check the internal consistency of the wrapped dictionary
1504 /// <returns>True if check passed</returns>
1505 public bool Check() { return dict.Check(); }
1513 /// A read-only wrapper for a sorted dictionary.
1515 /// <p>Suitable for wrapping a Dictionary. <see cref="T:C5.Dictionary!2"/></p>
1517 public class GuardedSortedDictionary
<K
,V
>: GuardedDictionary
<K
,V
>, ISortedDictionary
<K
,V
>
1521 ISortedDictionary
<K
,V
> sorteddict
;
1528 /// Wrap a sorted dictionary in a read-only wrapper
1530 /// <param name="sorteddict">the dictionary</param>
1531 public GuardedSortedDictionary(ISortedDictionary
<K
,V
> sorteddict
) :base(sorteddict
)
1532 { this.sorteddict = sorteddict; }
1536 #region ISortedDictionary<K,V> Members
1539 /// Get the entry in the wrapped dictionary whose key is the
1540 /// predecessor of a specified key.
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); }
1549 /// Get the entry in the wrapped dictionary whose key is the
1550 /// successor of a specified key.
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); }
1559 /// Get the entry in the wrapped dictionary whose key is the
1560 /// weak predecessor of a specified key.
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); }
1569 /// Get the entry in the wrapped dictionary whose key is the
1570 /// weak successor of a specified key.
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); }