From 6f0c429cc1fc58163757fe1bdaa42bc326c7a6bd Mon Sep 17 00:00:00 2001 From: Shad Storhaug Date: Tue, 31 Dec 2019 20:11:58 +0700 Subject: [PATCH] Added SCG.IDictionary to DictionaryBase (#53) --- C5.Tests/SupportClasses.cs | 2 + C5.Tests/Trees/Dictionary.cs | 260 ++++++++++++++++++ C5.UserGuideExamples/Graph.cs | 2 + C5.UserGuideExamples/MultiCollection.cs | 2 + C5/Arrays/ArrayList.cs | 6 +- C5/BaseClasses/ArrayBase.cs | 6 +- C5/BaseClasses/CollectionBase.cs | 2 +- C5/BaseClasses/CollectionValueBase.cs | 43 +++ C5/BaseClasses/DictionaryBase.cs | 94 ++++++- C5/Dictionaries/SortedDictionaryBase.cs | 8 +- C5/Enumerators/MappedCollectionValue.cs | 2 + .../MappedDirectedCollectionValue.cs | 2 + C5/Hashing/HashBag.cs | 8 +- C5/Hashing/HashSet.cs | 11 +- C5/Heaps/IntervalHeap.cs | 2 +- C5/Interfaces/ICollectionValue.cs | 15 +- C5/Interfaces/IDictionary.cs | 4 +- C5/Interfaces/IExtensible.cs | 4 +- C5/LinkedLists/HashedLinkedList.cs | 2 + C5/LinkedLists/LinkedList.cs | 2 + C5/Trees/TreeBag.cs | 4 + C5/Trees/TreeSet.cs | 3 + C5/WeakViewList.cs | 2 +- C5/Wrappers/GuardedCollection.cs | 12 +- C5/Wrappers/GuardedCollectionValue.cs | 37 +++ C5/Wrappers/GuardedDictionary.cs | 4 +- 26 files changed, 496 insertions(+), 43 deletions(-) diff --git a/C5.Tests/SupportClasses.cs b/C5.Tests/SupportClasses.cs index bc6a60b7..6e0aaf78 100644 --- a/C5.Tests/SupportClasses.cs +++ b/C5.Tests/SupportClasses.cs @@ -176,6 +176,8 @@ public override SCG.IEnumerator GetEnumerator() throw exception; } + public override bool IsReadOnly => true; + public override bool IsEmpty => false; public override int Count => contents.Length + 1; diff --git a/C5.Tests/Trees/Dictionary.cs b/C5.Tests/Trees/Dictionary.cs index 9cefb3b9..d4a82b2e 100644 --- a/C5.Tests/Trees/Dictionary.cs +++ b/C5.Tests/Trees/Dictionary.cs @@ -490,4 +490,264 @@ public void Dispose() } } } + + [TestFixture] + public class SCGIDictionary + { + private SCG.IDictionary dict; + + [SetUp] + public void Init() + { + dict = new TreeDictionary(new SC()) + { + { "A", "1" }, + { "C", "2" }, + { "E", "3" } + }; + } + + [TearDown] + public void Dispose() { dict = null; } + + [Test] + public void Add() + { + Assert.AreEqual(3, dict.Count); + dict.Add("S", "4"); + Assert.AreEqual(4, dict.Count); + } + + [Test] + public void ContainsKey() + { + Assert.IsTrue(dict.ContainsKey("A")); + Assert.IsFalse(dict.ContainsKey("Z")); + } + + [Test] + public void Remove() + { + Assert.AreEqual(3, dict.Count); + Assert.IsTrue(dict.Remove("A")); + Assert.AreEqual(2, dict.Count); + Assert.IsFalse(dict.Remove("Z")); + Assert.AreEqual(2, dict.Count); + } + + [Test] + public void TryGetValue() + { + Assert.IsTrue(dict.TryGetValue("C", out string value)); + Assert.AreEqual("2", value); + Assert.IsFalse(dict.TryGetValue("Z", out value)); + Assert.IsNull(value); + } + + [Test] + public void GetItem() + { + Assert.AreEqual("3", dict["E"]); + Assert.Throws(() => { var x = dict["Z"]; }); + } + + [Test] + public void SetItem() + { + dict["C"] = "9"; + Assert.AreEqual("9", dict["C"]); + dict["Z"] = "5"; + Assert.AreEqual("5", dict["Z"]); + } + + // ICollection> + [Test] + public void Clear() + { + dict.Clear(); + Assert.AreEqual(0, dict.Count); + } + + [Test] + public void Contains() + { + Assert.IsTrue(dict.Contains(new SCG.KeyValuePair("C", "2"))); + Assert.IsFalse(dict.Contains(new SCG.KeyValuePair("D", "2"))); + Assert.IsFalse(dict.Contains(new SCG.KeyValuePair("C", "6"))); + } + + [Test] + public void CopyTo() + { + var pairs = new SCG.KeyValuePair[dict.Count]; + dict.CopyTo(pairs, 0); + Assert.AreEqual("C", pairs[1].Key); + Assert.AreEqual("2", pairs[1].Value); + Assert.AreEqual("E", pairs[2].Key); + Assert.AreEqual("3", pairs[2].Value); + } + + [Test] + public void RemovePair() + { + Assert.AreEqual(3, dict.Count); + Assert.IsTrue(dict.Remove(new SCG.KeyValuePair("A", "1"))); + Assert.AreEqual(2, dict.Count); + Assert.IsFalse(dict.Remove(new SCG.KeyValuePair("Z", "9"))); + Assert.AreEqual(2, dict.Count); + } + + [Test] + public void Count() + { + Assert.AreEqual(3, dict.Count); + } + + [Test] + public void IsReadOnly() + { + Assert.AreEqual(false, dict.IsReadOnly); + } + + [Test] + public void GetEnumerable() + { + var enumerable = dict.GetEnumerator(); + Assert.IsTrue(enumerable.MoveNext()); + Assert.AreEqual(new SCG.KeyValuePair("A", "1"), enumerable.Current); + Assert.IsTrue(enumerable.MoveNext()); + Assert.AreEqual(new SCG.KeyValuePair("C", "2"), enumerable.Current); + Assert.IsTrue(enumerable.MoveNext()); + Assert.AreEqual(new SCG.KeyValuePair("E", "3"), enumerable.Current); + Assert.IsFalse(enumerable.MoveNext()); + } + + [Test] + public void Keys_GetEnumerable() + { + var enumerable = dict.Keys.GetEnumerator(); + Assert.IsTrue(enumerable.MoveNext()); + Assert.AreEqual("A", enumerable.Current); + Assert.IsTrue(enumerable.MoveNext()); + Assert.AreEqual("C", enumerable.Current); + Assert.IsTrue(enumerable.MoveNext()); + Assert.AreEqual("E", enumerable.Current); + Assert.IsFalse(enumerable.MoveNext()); + } + + [Test] + public void Keys_Count() + { + Assert.AreEqual(3, dict.Keys.Count); + dict.Remove("C"); + Assert.AreEqual(2, dict.Keys.Count); + } + + [Test] + public void Keys_IsReadOnly() + { + Assert.AreEqual(true, dict.Keys.IsReadOnly); + } + + [Test] + public void Keys_Add() + { + Assert.Throws(() => dict.Keys.Add("Foo")); + } + + [Test] + public void Keys_Clear() + { + Assert.Throws(() => dict.Keys.Clear()); + } + + [Test] + public void Keys_Contains() + { + Assert.IsTrue(dict.Keys.Contains("A")); + Assert.IsFalse(dict.Keys.Contains("B")); + } + + [Test] + public void Keys_CopyTo() + { + var keys = new string[dict.Keys.Count + 2]; + dict.Keys.CopyTo(keys, 1); + Assert.AreEqual(null, keys[0]); + Assert.AreEqual("A", keys[1]); + Assert.AreEqual("C", keys[2]); + Assert.AreEqual("E", keys[3]); + Assert.AreEqual(null, keys[4]); + } + + [Test] + public void Keys_Remove() + { + Assert.Throws(() => dict.Keys.Remove("Foo")); + } + + [Test] + public void Values_GetEnumerable() + { + var enumerable = dict.Values.GetEnumerator(); + Assert.IsTrue(enumerable.MoveNext()); + Assert.AreEqual("1", enumerable.Current); + Assert.IsTrue(enumerable.MoveNext()); + Assert.AreEqual("2", enumerable.Current); + Assert.IsTrue(enumerable.MoveNext()); + Assert.AreEqual("3", enumerable.Current); + Assert.IsFalse(enumerable.MoveNext()); + } + + [Test] + public void Values_Count() + { + Assert.AreEqual(3, dict.Values.Count); + dict.Remove("C"); + Assert.AreEqual(2, dict.Values.Count); + } + + [Test] + public void Values_IsReadOnly() + { + Assert.AreEqual(true, dict.Values.IsReadOnly); + } + + [Test] + public void Values_Add() + { + Assert.Throws(() => dict.Values.Add("Foo")); + } + + [Test] + public void Values_Clear() + { + Assert.Throws(() => dict.Values.Clear()); + } + + [Test] + public void Values_Contains() + { + Assert.IsTrue(dict.Values.Contains("1")); + Assert.IsFalse(dict.Values.Contains("9")); + } + + [Test] + public void Values_CopyTo() + { + var values = new string[dict.Values.Count + 2]; + dict.Values.CopyTo(values, 1); + Assert.AreEqual(null, values[0]); + Assert.AreEqual("1", values[1]); + Assert.AreEqual("2", values[2]); + Assert.AreEqual("3", values[3]); + Assert.AreEqual(null, values[4]); + } + + [Test] + public void Values_Remove() + { + Assert.Throws(() => dict.Values.Remove("1")); + } + } } diff --git a/C5.UserGuideExamples/Graph.cs b/C5.UserGuideExamples/Graph.cs index 0256be8f..23f150c2 100644 --- a/C5.UserGuideExamples/Graph.cs +++ b/C5.UserGuideExamples/Graph.cs @@ -573,6 +573,8 @@ internal EdgesValue(HashGraph g) _graph = g; } + public override bool IsReadOnly => true; + public override bool IsEmpty => _graph.EdgeCount == 0; public override int Count => _graph.EdgeCount; diff --git a/C5.UserGuideExamples/MultiCollection.cs b/C5.UserGuideExamples/MultiCollection.cs index e7460d34..e7f7d5ee 100644 --- a/C5.UserGuideExamples/MultiCollection.cs +++ b/C5.UserGuideExamples/MultiCollection.cs @@ -22,6 +22,8 @@ public BasicCollectionValue(SCG.IEnumerable e, Func chooser, int c) Count = c; } + public override bool IsReadOnly => true; + public override int Count { get; } public override Speed CountSpeed => Speed.Constant; diff --git a/C5/Arrays/ArrayList.cs b/C5/Arrays/ArrayList.cs index de323b2f..3a8eabb1 100644 --- a/C5/Arrays/ArrayList.cs +++ b/C5/Arrays/ArrayList.cs @@ -1481,7 +1481,7 @@ public override bool UnsequencedEquals(ICollection that) /// /// The value to check for. /// True if the items is in this collection. - public virtual bool Contains(T item) + public override bool Contains(T item) { ValidityCheck(); return IndexOfInner(item) >= 0; } @@ -1611,7 +1611,7 @@ public virtual bool UpdateOrAdd(T item, out T olditem) /// /// The value to remove. /// True if the item was found (and removed). - public virtual bool Remove(T item) + public override bool Remove(T item) { UpdateCheck(); @@ -2142,7 +2142,7 @@ public override bool Check() /// /// The item to add. /// True - public virtual bool Add(T item) + public override bool Add(T item) { UpdateCheck(); diff --git a/C5/BaseClasses/ArrayBase.cs b/C5/BaseClasses/ArrayBase.cs index c6873581..6e010f82 100644 --- a/C5/BaseClasses/ArrayBase.cs +++ b/C5/BaseClasses/ArrayBase.cs @@ -125,7 +125,7 @@ protected ArrayBase(int capacity, System.Collections.Generic.IEqualityComparer /// Remove all items and reset size of internal array container. /// - public virtual void Clear() + public override void Clear() { UpdateCheck(); array = new T[8]; @@ -238,6 +238,10 @@ internal Range(ArrayBase thebase, int start, int count, bool forwards) /// True if this collection is empty. public override bool IsEmpty { get { thebase.ModifyCheck(stamp); return count == 0; } } + /// + /// Gets a value indicating whether the is read-only. Always returns true. + /// + public override bool IsReadOnly => true; /// /// diff --git a/C5/BaseClasses/CollectionBase.cs b/C5/BaseClasses/CollectionBase.cs index 0ecef724..c4eb3435 100644 --- a/C5/BaseClasses/CollectionBase.cs +++ b/C5/BaseClasses/CollectionBase.cs @@ -287,7 +287,7 @@ protected virtual void UpdateCheck() /// /// /// True if this collection is read only - public virtual bool IsReadOnly => isReadOnlyBase; + public override bool IsReadOnly => isReadOnlyBase; #endregion diff --git a/C5/BaseClasses/CollectionValueBase.cs b/C5/BaseClasses/CollectionValueBase.cs index 81911ff5..2c06cc14 100644 --- a/C5/BaseClasses/CollectionValueBase.cs +++ b/C5/BaseClasses/CollectionValueBase.cs @@ -653,5 +653,48 @@ public override string ToString() { return ToString(null, null); } + + #region SCG.ICollection Members + + /// + /// Gets a value indicating whether the is read-only. + /// + public abstract bool IsReadOnly { get; } + + /// + /// Adds an item to the . + /// + /// The default implementation throws a . Override to provide an implementation. + /// + /// The object to add to the . + public virtual bool Add(T item) => throw new ReadOnlyCollectionException(); + + void System.Collections.Generic.ICollection.Add(T item) => this.Add(item); + + /// + /// Removes all items from the . + /// + /// The default implementation throws a . Override to provide an implementation. + /// + public virtual void Clear() => throw new ReadOnlyCollectionException(); + + /// + /// Determines whether the contains a specific value. + /// + /// The object to locate in the . + /// true if item is found in the ; otherwise, false. + public virtual bool Contains(T item) => this.Exists((thisItem) => EqualityComparer.Default.Equals(thisItem, item)); + + /// + /// Removes the first occurrence of a specific object from the . + /// + /// The default implementation throws a . Override to provide an implementation. + /// + /// The object to remove from the . + /// true if item was successfully removed from the ; otherwise, false. + /// This method also returns false if item is not found in the original . + public virtual bool Remove(T item) => throw new ReadOnlyCollectionException(); + + #endregion } } \ No newline at end of file diff --git a/C5/BaseClasses/DictionaryBase.cs b/C5/BaseClasses/DictionaryBase.cs index 832e6699..0a82202c 100644 --- a/C5/BaseClasses/DictionaryBase.cs +++ b/C5/BaseClasses/DictionaryBase.cs @@ -1,5 +1,5 @@ using System; -using System.Collections.Generic; +using SCG = System.Collections.Generic; namespace C5 { @@ -9,7 +9,7 @@ namespace C5 /// /// [Serializable] - public abstract class DictionaryBase : CollectionValueBase>, IDictionary + public abstract class DictionaryBase : CollectionValueBase>, IDictionary, SCG.IDictionary { /// /// The set collection of entries underlying this dictionary implementation @@ -186,7 +186,7 @@ public virtual bool Remove(K key, out V value) /// /// Remove all entries from the dictionary /// - public virtual void Clear() { pairs.Clear(); } + public override void Clear() { pairs.Clear(); } /// /// @@ -207,7 +207,7 @@ public virtual bool Contains(K key) } [Serializable] - private class LiftedEnumerable : IEnumerable> where H : K + private class LiftedEnumerable : SCG.IEnumerable> where H : K { private readonly System.Collections.Generic.IEnumerable keys; public LiftedEnumerable(System.Collections.Generic.IEnumerable keys) { this.keys = keys; } @@ -379,6 +379,8 @@ public override System.Collections.Generic.IEnumerator GetEnumerator() public override int Count => pairs.Count; public override Speed CountSpeed => Speed.Constant; + + public override bool IsReadOnly => true; } [Serializable] @@ -405,6 +407,8 @@ public override System.Collections.Generic.IEnumerator GetEnumerator() public override int Count => pairs.Count; public override Speed CountSpeed => pairs.CountSpeed; + + public override bool IsReadOnly => true; } #endregion @@ -455,8 +459,8 @@ public virtual V this[K key] /// /// /// - /// True if dictionary is read only - public virtual bool IsReadOnly => pairs.IsReadOnly; + /// True if dictionary is read only + public override bool IsReadOnly => pairs.IsReadOnly; /// @@ -517,5 +521,83 @@ public override bool Show(System.Text.StringBuilder stringbuilder, ref int rest, { return Showing.ShowDictionary(this, stringbuilder, ref rest, formatProvider); } + + #region SCG.IDictionary Members + + SCG.ICollection SCG.IDictionary.Keys => this.Keys; + + SCG.ICollection SCG.IDictionary.Values => this.Values; + + int SCG.ICollection>.Count => this.Count; + + bool SCG.ICollection>.IsReadOnly => this.IsReadOnly; + + V SCG.IDictionary.this[K key] { get => this[key]; set => this[key] = value; } + + void SCG.IDictionary.Add(K key, V value) + { + this.Add(key, value); + } + + bool SCG.IDictionary.ContainsKey(K key) + { + return this.Contains(key); + } + + bool SCG.IDictionary.Remove(K key) + { + return this.Remove(key); + } + + bool SCG.IDictionary.TryGetValue(K key, out V value) + { + SCG.KeyValuePair p = new SCG.KeyValuePair(key, default); + + bool result = pairs.Find(ref p); + value = p.Value; + return result; + } + + void SCG.ICollection>.Add(SCG.KeyValuePair item) + { + this.Add(item.Key, item.Value); + } + + void SCG.ICollection>.Clear() + { + this.Clear(); + } + + bool SCG.ICollection>.Contains(SCG.KeyValuePair item) + { + foreach (var thisItem in this) + if (thisItem.Equals(item)) + return true; + + return false; + } + + void SCG.ICollection>.CopyTo(SCG.KeyValuePair[] array, int arrayIndex) + { + if (arrayIndex < 0 || arrayIndex + Count > array.Length) + throw new ArgumentOutOfRangeException(nameof(arrayIndex)); + + foreach (var item in this) + array[arrayIndex++] = new SCG.KeyValuePair(item.Key, item.Value); + } + + bool SCG.ICollection>.Remove(SCG.KeyValuePair item) + { + return this.Remove(item.Key); + } + + SCG.IEnumerator> SCG.IEnumerable>.GetEnumerator() + { + foreach (var item in this) + yield return new SCG.KeyValuePair(item.Key, item.Value); + } + + #endregion + } } \ No newline at end of file diff --git a/C5/Dictionaries/SortedDictionaryBase.cs b/C5/Dictionaries/SortedDictionaryBase.cs index 17e23aa8..88f5b825 100644 --- a/C5/Dictionaries/SortedDictionaryBase.cs +++ b/C5/Dictionaries/SortedDictionaryBase.cs @@ -424,7 +424,7 @@ public IDirectedCollectionValue RangeAll() #region ICollection Members public Speed ContainsSpeed => sorteddict.ContainsSpeed; - public bool Contains(K key) { return sorteddict.Contains(key); ; } + public override bool Contains(K key) { return sorteddict.Contains(key); } public int ContainsCount(K item) { return sorteddict.Contains(item) ? 1 : 0; } @@ -479,7 +479,7 @@ public bool Find(ref K item) public bool UpdateOrAdd(K item, out K olditem) { throw new ReadOnlyCollectionException(); } - public bool Remove(K item) { throw new ReadOnlyCollectionException(); } + public override bool Remove(K item) { throw new ReadOnlyCollectionException(); } public bool Remove(K item, out K removeditem) { throw new ReadOnlyCollectionException(); } @@ -487,7 +487,7 @@ public bool Find(ref K item) public void RemoveAll(SCG.IEnumerable items) { throw new ReadOnlyCollectionException(); } - public void Clear() { throw new ReadOnlyCollectionException(); } + public override void Clear() { throw new ReadOnlyCollectionException(); } public void RetainAll(SCG.IEnumerable items) { throw new ReadOnlyCollectionException(); } @@ -500,7 +500,7 @@ public bool Find(ref K item) public bool DuplicatesByCounting => true; - public bool Add(K item) { throw new ReadOnlyCollectionException(); } + public override bool Add(K item) { throw new ReadOnlyCollectionException(); } void SCG.ICollection.Add(K item) { throw new ReadOnlyCollectionException(); } diff --git a/C5/Enumerators/MappedCollectionValue.cs b/C5/Enumerators/MappedCollectionValue.cs index 61228ba1..c9f3ca89 100644 --- a/C5/Enumerators/MappedCollectionValue.cs +++ b/C5/Enumerators/MappedCollectionValue.cs @@ -22,6 +22,8 @@ protected MappedCollectionValue(ICollectionValue collectionValue) public override Speed CountSpeed => collectionValue.CountSpeed; + public override bool IsReadOnly => collectionValue.IsReadOnly; + public override System.Collections.Generic.IEnumerator GetEnumerator() { foreach (var item in collectionValue) diff --git a/C5/Enumerators/MappedDirectedCollectionValue.cs b/C5/Enumerators/MappedDirectedCollectionValue.cs index d7473df5..27b2a69f 100644 --- a/C5/Enumerators/MappedDirectedCollectionValue.cs +++ b/C5/Enumerators/MappedDirectedCollectionValue.cs @@ -26,6 +26,8 @@ protected MappedDirectedCollectionValue(IDirectedCollectionValue directedColl public override Speed CountSpeed => directedCollectionValue.CountSpeed; + public override bool IsReadOnly => directedCollectionValue.IsReadOnly; + public override IDirectedCollectionValue Backwards() { var ret = (MappedDirectedCollectionValue)MemberwiseClone(); diff --git a/C5/Hashing/HashBag.cs b/C5/Hashing/HashBag.cs index 3cb09c13..46c72b38 100644 --- a/C5/Hashing/HashBag.cs +++ b/C5/Hashing/HashBag.cs @@ -81,7 +81,7 @@ public HashBag(int capacity, double fill, SCG.IEqualityComparer itemequalityC /// /// The item to look for /// True if bag contains item - public virtual bool Contains(T item) + public override bool Contains(T item) { return dict.Contains(new System.Collections.Generic.KeyValuePair(item, 0)); } @@ -217,7 +217,7 @@ public virtual bool UpdateOrAdd(T item, out T olditem) /// /// The item to remove /// True if item was (found and) removed - public virtual bool Remove(T item) + public override bool Remove(T item) { var p = new SCG.KeyValuePair(item, 0); @@ -321,7 +321,7 @@ public virtual void RemoveAll(SCG.IEnumerable items) /// /// Remove all items from the bag, resetting internal table to initial size. /// - public virtual void Clear() + public override void Clear() { UpdateCheck(); if (size == 0) @@ -569,7 +569,7 @@ public override void CopyTo(T[] array, int index) /// /// The item to add. /// Always true - public virtual bool Add(T item) + public override bool Add(T item) { UpdateCheck(); Add(ref item); diff --git a/C5/Hashing/HashSet.cs b/C5/Hashing/HashSet.cs index 434a0dde..e01bf47b 100644 --- a/C5/Hashing/HashSet.cs +++ b/C5/Hashing/HashSet.cs @@ -451,7 +451,7 @@ public virtual bool UpdateOrAdd(T item, out T olditem) /// /// The item to remove /// True if item was (found and) removed - public virtual bool Remove(T item) + public override bool Remove(T item) { UpdateCheck(); if (Remove(ref item)) @@ -515,7 +515,7 @@ public virtual void RemoveAll(SCG.IEnumerable items) /// /// Remove all items from the set, resetting internal table to initial size. /// - public virtual void Clear() + public override void Clear() { UpdateCheck(); int oldsize = size; @@ -743,7 +743,7 @@ public override SCG.IEnumerator GetEnumerator() /// /// The item to add. /// True if item was added (i.e. not found) - public virtual bool Add(T item) + public override bool Add(T item) { UpdateCheck(); return !SearchOrAdd(ref item, true, false, true); @@ -753,10 +753,7 @@ public virtual bool Add(T item) /// Add an item to this set. /// /// The item to add. - void SCG.ICollection.Add(T item) - { - Add(item); - } + void SCG.ICollection.Add(T item) => Add(item); /// /// Add the elements from another collection with a more specialized item type diff --git a/C5/Heaps/IntervalHeap.cs b/C5/Heaps/IntervalHeap.cs index 10891f5c..ef253901 100644 --- a/C5/Heaps/IntervalHeap.cs +++ b/C5/Heaps/IntervalHeap.cs @@ -332,7 +332,7 @@ public T DeleteMax() /// ReadOnlyCollectionException /// /// True if this collection is read-only. - public bool IsReadOnly => false; + public override bool IsReadOnly => false; /// /// diff --git a/C5/Interfaces/ICollectionValue.cs b/C5/Interfaces/ICollectionValue.cs index a05c83a5..5050b132 100644 --- a/C5/Interfaces/ICollectionValue.cs +++ b/C5/Interfaces/ICollectionValue.cs @@ -10,8 +10,17 @@ namespace C5 /// collection. The main usage for this interface is to be the return type of /// query operations on generic collection. /// - public interface ICollectionValue : IEnumerable, IShowable + public interface ICollectionValue : IEnumerable, IShowable, System.Collections.Generic.ICollection { + /// + /// Add an item to this collection if possible. If this collection has set + /// semantics, the item will be added if not already in the collection. If + /// bag semantics, the item will always be added. + /// + /// The item to add. + /// True if item was added. + new bool Add(T item); + /// /// A flag bitmap of the events subscribable to by this collection. /// @@ -63,7 +72,7 @@ public interface ICollectionValue : IEnumerable, IShowable /// /// /// The number of items in this collection - int Count { get; } + new int Count { get; } /// /// The value is symbolic indicating the type of asymptotic complexity @@ -79,7 +88,7 @@ public interface ICollectionValue : IEnumerable, IShowable /// /// The array to copy to /// The index at which to copy the first item - void CopyTo(T[] array, int index); + new void CopyTo(T[] array, int index); /// /// Create an array with the items of this collection (in the same order as an diff --git a/C5/Interfaces/IDictionary.cs b/C5/Interfaces/IDictionary.cs index 26bd0bd9..60f91165 100644 --- a/C5/Interfaces/IDictionary.cs +++ b/C5/Interfaces/IDictionary.cs @@ -27,7 +27,7 @@ public interface IDictionary : ICollectionValue /// True if dictionary is read-only - bool IsReadOnly { get; } + new bool IsReadOnly { get; } /// @@ -110,7 +110,7 @@ void AddAll(IEnumerable> ent /// /// Remove all entries from the dictionary /// - void Clear(); + new void Clear(); /// diff --git a/C5/Interfaces/IExtensible.cs b/C5/Interfaces/IExtensible.cs index 48765ade..f2897847 100644 --- a/C5/Interfaces/IExtensible.cs +++ b/C5/Interfaces/IExtensible.cs @@ -14,7 +14,7 @@ public interface IExtensible : ICollectionValue /// ReadOnlyCollectionException /// /// True if this collection is read-only. - bool IsReadOnly { get; } + new bool IsReadOnly { get; } //TODO: wonder where the right position of this is /// @@ -49,7 +49,7 @@ public interface IExtensible : ICollectionValue /// /// The item to add. /// True if item was added. - bool Add(T item); + new bool Add(T item); /// /// Add the elements from another collection with a more specialized item type diff --git a/C5/LinkedLists/HashedLinkedList.cs b/C5/LinkedLists/HashedLinkedList.cs index 89fcbddd..2a232233 100644 --- a/C5/LinkedLists/HashedLinkedList.cs +++ b/C5/LinkedLists/HashedLinkedList.cs @@ -1119,6 +1119,8 @@ internal Range(HashedLinkedList list, int start, int count, bool forwards) } } + public override bool IsReadOnly => true; + public override bool IsEmpty { get { list.ModifyCheck(rangestamp); return count == 0; } } public override int Count { get { list.ModifyCheck(rangestamp); return count; } } diff --git a/C5/LinkedLists/LinkedList.cs b/C5/LinkedLists/LinkedList.cs index f9f86221..03a7f381 100644 --- a/C5/LinkedLists/LinkedList.cs +++ b/C5/LinkedLists/LinkedList.cs @@ -776,6 +776,8 @@ internal Range(LinkedList list, int start, int count, bool forwards) } } + public override bool IsReadOnly => true; + public override bool IsEmpty { get { list.ModifyCheck(rangestamp); return count == 0; } } public override int Count { get { list.ModifyCheck(rangestamp); return count; } } diff --git a/C5/Trees/TreeBag.cs b/C5/Trees/TreeBag.cs index 026d96e2..1df0d9ac 100644 --- a/C5/Trees/TreeBag.cs +++ b/C5/Trees/TreeBag.cs @@ -2310,6 +2310,7 @@ private class Multiplicities : CollectionValueBase treebag.IsReadOnly; public override bool IsEmpty => treebag.IsEmpty; public override int Count { get { int i = 0; foreach (System.Collections.Generic.KeyValuePair p in this) { i++; } return i; } } //TODO: make better public override Speed CountSpeed => Speed.Linear; //TODO: make better @@ -2701,6 +2702,8 @@ internal Interval(TreeBag tree, int start, int count, bool forwards) this.tree = tree; stamp = tree.stamp; } + public override bool IsReadOnly => true; + public override bool IsEmpty => length == 0; public override int Count => length; @@ -4288,6 +4291,7 @@ public override IDirectedCollectionValue Backwards() IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } + public override bool IsReadOnly => true; public override bool IsEmpty => size == 0; diff --git a/C5/Trees/TreeSet.cs b/C5/Trees/TreeSet.cs index 2c3afeb4..6e265d0f 100644 --- a/C5/Trees/TreeSet.cs +++ b/C5/Trees/TreeSet.cs @@ -2908,6 +2908,8 @@ internal Interval(TreeSet tree, int start, int count, bool forwards) this.tree = tree; stamp = tree.stamp; } + public override bool IsReadOnly => true; + public override bool IsEmpty => length == 0; public override int Count => length; @@ -4418,6 +4420,7 @@ public override IDirectedCollectionValue Backwards() IDirectedEnumerable IDirectedEnumerable.Backwards() { return Backwards(); } + public override bool IsReadOnly => true; public override bool IsEmpty => size == 0; diff --git a/C5/WeakViewList.cs b/C5/WeakViewList.cs index 5d64b0d2..11f5fe9c 100644 --- a/C5/WeakViewList.cs +++ b/C5/WeakViewList.cs @@ -58,7 +58,7 @@ public SCG.IEnumerator GetEnumerator() { //V view = n.weakview.Target as V; //This provokes a bug in the beta1 verifyer object o = n.weakview.Target; - V view = o is V ? (V)o : null; + V? view = o is V ? (V)o : null; if (view == null) { Remove(n); diff --git a/C5/Wrappers/GuardedCollection.cs b/C5/Wrappers/GuardedCollection.cs index 947769ba..c9b24606 100644 --- a/C5/Wrappers/GuardedCollection.cs +++ b/C5/Wrappers/GuardedCollection.cs @@ -37,7 +37,7 @@ public GuardedCollection(ICollection collection) /// (This is a read-only wrapper) /// /// True - public virtual bool IsReadOnly => true; + public override bool IsReadOnly => true; /// @@ -65,7 +65,7 @@ public virtual bool UnsequencedEquals(ICollection that) /// /// The item /// True if found - public virtual bool Contains(T item) { return collection.Contains(item); } + public override bool Contains(T item) => collection.Contains(item); /// @@ -73,7 +73,7 @@ public virtual bool UnsequencedEquals(ICollection that) /// /// The item /// The number of copies - public virtual int ContainsCount(T item) { return collection.ContainsCount(item); } + public virtual int ContainsCount(T item) => collection.ContainsCount(item); /// /// @@ -153,7 +153,7 @@ public virtual bool UpdateOrAdd(T item, out T olditem) /// since this is a read-only wrapper /// /// - public virtual bool Remove(T item) + public override bool Remove(T item) { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } @@ -185,7 +185,7 @@ public virtual void RemoveAll(System.Collections.Generic.IEnumerable items) /// /// /// since this is a read-only wrapper - public virtual void Clear() + public override void Clear() { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); } @@ -235,7 +235,7 @@ public virtual void RetainAll(System.Collections.Generic.IEnumerable items) /// since this is a read-only wrapper /// /// - public virtual bool Add(T item) + public override bool Add(T item) { throw new ReadOnlyCollectionException(); } /// diff --git a/C5/Wrappers/GuardedCollectionValue.cs b/C5/Wrappers/GuardedCollectionValue.cs index 62293403..6238a2f7 100644 --- a/C5/Wrappers/GuardedCollectionValue.cs +++ b/C5/Wrappers/GuardedCollectionValue.cs @@ -219,6 +219,43 @@ public GuardedCollectionValue(ICollectionValue collectionvalue) #endregion + #region SCG.ICollection Members + + /// + /// Gets a value indicating whether the is read-only. + /// + public virtual bool IsReadOnly => collectionvalue.IsReadOnly; + + /// + /// Adds an item to the . + /// + /// The object to add to the . + public virtual bool Add(T item) => collectionvalue.Add(item); + + void System.Collections.Generic.ICollection.Add(T item) => this.Add(item); + + /// + /// Removes all items from the . + /// + public virtual void Clear() => collectionvalue.Clear(); + + /// + /// Determines whether the contains a specific value. + /// + /// The object to locate in the . + /// true if item is found in the ; otherwise, false. + public virtual bool Contains(T item) => collectionvalue.Contains(item); + + /// + /// Removes the first occurrence of a specific object from the . + /// + /// The object to remove from the . + /// true if item was successfully removed from the ; otherwise, false. + /// This method also returns false if item is not found in the original . + public virtual bool Remove(T item) => collectionvalue.Remove(item); + + #endregion + #region IShowable Members /// diff --git a/C5/Wrappers/GuardedDictionary.cs b/C5/Wrappers/GuardedDictionary.cs index 248325d0..a073e94f 100644 --- a/C5/Wrappers/GuardedDictionary.cs +++ b/C5/Wrappers/GuardedDictionary.cs @@ -50,7 +50,7 @@ public V this[K key] /// (This is a read-only wrapper) /// /// True - public bool IsReadOnly => true; + public override bool IsReadOnly => true; /// /// The collection of keys of the wrapped dictionary @@ -100,7 +100,7 @@ public void AddAll(SCG.IEnumerable> items) /// /// /// since this is a read-only wrapper - public void Clear() => throw new ReadOnlyCollectionException(); + public override void Clear() => throw new ReadOnlyCollectionException(); /// ///