dummy;
return myDictionary.tree.Find(pair, true, false, out dummy);
}
}
#endregion KeyValuePairs collection
#region Views
///
/// Returns a View collection that can be used for enumerating the keys and values in the collection in
/// reversed order.
///
///
///Typically, this method is used in conjunction with a foreach statement. For example:
///
/// foreach(KeyValuePair<TKey, TValue> pair in dictionary.Reversed()) {
/// // process pair
/// }
///
/// If an entry is added to or deleted from the dictionary while the View is being enumerated, then
/// the enumeration will end with an InvalidOperationException.
///Calling Reverse does not copy the data in the dictionary, and the operation takes constant time.
///
/// An OrderedDictionary.View of key-value pairs in reverse order.
public View Reversed()
{
return new View(this, tree.EntireRangeTester, true, true);
}
///
/// Returns a collection that can be used for enumerating some of the keys and values in the collection.
/// Only keys that are greater than and
/// less than are included. The keys are enumerated in sorted order.
/// Keys equal to the end points of the range can be included or excluded depending on the
/// and parameters.
///
///
///If is greater than or equal to , the returned collection is empty.
///The sorted order of the keys is determined by the comparison instance or delegate used
/// to create the dictionary.
///Typically, this property is used in conjunction with a foreach statement. For example:
///
/// foreach(KeyValuePair<TKey, TValue> pair in dictionary.Range(from, true, to, false)) {
/// // process pair
/// }
///
///Calling Range does not copy the data in the dictionary, and the operation takes constant time.
/// The lower bound of the range.
/// If true, the lower bound is inclusive--keys equal to the lower bound will
/// be included in the range. If false, the lower bound is exclusive--keys equal to the lower bound will not
/// be included in the range.
/// The upper bound of the range.
/// If true, the upper bound is inclusive--keys equal to the upper bound will
/// be included in the range. If false, the upper bound is exclusive--keys equal to the upper bound will not
/// be included in the range.
/// An OrderedMultiDictionary.View of key-value pairs in the given range.
public View Range(TKey from, bool fromInclusive, TKey to, bool toInclusive)
{
return new View(this, DoubleBoundedKeyRangeTester(from, fromInclusive, to, toInclusive), false, false);
}
///
/// Returns a collection that can be used for enumerating some of the keys and values in the collection.
/// Only keys that are greater than (and optionally, equal to) are included.
/// The keys are enumerated in sorted order. Keys equal to can be included
/// or excluded depending on the parameter.
///
///
///The sorted order of the keys is determined by the comparison instance or delegate used
/// to create the dictionary.
///Typically, this property is used in conjunction with a foreach statement. For example:
///
/// foreach(KeyValuePair<TKey, TValue> pair in dictionary.RangeFrom(from, true)) {
/// // process pair
/// }
///
///Calling RangeFrom does not copy of the data in the dictionary, and the operation takes constant time.
///
/// The lower bound of the range.
/// If true, the lower bound is inclusive--keys equal to the lower bound will
/// be included in the range. If false, the lower bound is exclusive--keys equal to the lower bound will not
/// be included in the range.
/// An OrderedMultiDictionary.View of key-value pairs in the given range.
public View RangeFrom(TKey from, bool fromInclusive)
{
return new View(this, LowerBoundedKeyRangeTester(from, fromInclusive), false, false);
}
///
/// Returns a collection that can be used for enumerating some of the keys and values in the collection.
/// Only items that are less than (and optionally, equal to) are included.
/// The items are enumerated in sorted order. Items equal to can be included
/// or excluded depending on the parameter.
///
///
///The sorted order of the keys is determined by the comparison instance or delegate used
/// to create the dictionary.
///Typically, this property is used in conjunction with a foreach statement. For example:
///
/// foreach(KeyValuePair<TKey, TValue> pair in dictionary.RangeFrom(from, false)) {
/// // process pair
/// }
///
///Calling RangeTo does not copy the data in the dictionary, and the operation takes constant time.
///
/// The upper bound of the range.
/// If true, the upper bound is inclusive--keys equal to the upper bound will
/// be included in the range. If false, the upper bound is exclusive--keys equal to the upper bound will not
/// be included in the range.
/// An OrderedMultiDictionary.View of key-value pairs in the given range.
public View RangeTo(TKey to, bool toInclusive)
{
return new View(this, UpperBoundedKeyRangeTester(to, toInclusive), false, false);
}
#endregion Views
///
/// The OrderedMultiDictionary<TKey,TValue>.View class is used to look at a subset of the keys and values
/// inside an ordered multi-dictionary. It is returned from the Range, RangeTo, RangeFrom, and Reversed methods.
///
///
/// Views are dynamic. If the underlying dictionary changes, the view changes in sync. If a change is made
/// to the view, the underlying dictionary changes accordingly.
///Typically, this class is used in conjunction with a foreach statement to enumerate the keys
/// and values in a subset of the OrderedMultiDictionary. For example:
///
/// foreach(KeyValuePair<TKey, TValue> pair in dictionary.Range(from, to)) {
/// // process pair
/// }
///
///
[Serializable]
public class View : MultiDictionaryBase
{
private OrderedMultiDictionary myDictionary;
private RedBlackTree>.RangeTester rangeTester; // range tester for the range being used.
private bool entireTree; // is the view the whole tree?
private bool reversed; // is the view reversed?
///
/// Initialize the View.
///
/// Associated OrderedMultiDictionary to be viewed.
/// Range tester that defines the range being used.
/// If true, then rangeTester defines the entire tree.
/// Is the view enuemerated in reverse order?
internal View(OrderedMultiDictionary myDictionary, RedBlackTree>.RangeTester rangeTester, bool entireTree, bool reversed)
{
this.myDictionary = myDictionary;
this.rangeTester = rangeTester;
this.entireTree = entireTree;
this.reversed = reversed;
}
///
/// Determine if the given key lies within the bounds of this view.
///
/// Key to test.
/// True if the key is within the bounds of this view.
private bool KeyInView(TKey key)
{
return rangeTester(NewPair(key, default(TValue))) == 0;
}
///
/// Enumerate all the keys in the dictionary.
///
/// An IEnumerator<TKey> that enumerates all of the keys in the collection that
/// have at least one value associated with them.
protected sealed override IEnumerator EnumerateKeys()
{
return myDictionary.EnumerateKeys(rangeTester, reversed);
}
///
/// Enumerate all of the values associated with a given key. If the key exists and has values associated with it, an enumerator for those
/// values is returned throught . If the key does not exist, false is returned.
///
/// The key to get values for.
/// If true is returned, this parameter receives an enumerators that
/// enumerates the values associated with that key.
/// True if the key exists and has values associated with it. False otherwise.
protected sealed override bool TryEnumerateValuesForKey(TKey key, out IEnumerator values)
{
if (!KeyInView(key)) {
values = null;
return false;
}
else
return myDictionary.TryEnumerateValuesForKey(key, out values);
}
///
/// Number of keys in this view.
///
/// Number of keys that lie within the bounds the view.
public sealed override int Count
{
get
{
if (entireTree)
return myDictionary.Count;
else {
int count = 0;
using (IEnumerator enumKeys = myDictionary.EnumerateKeys(rangeTester, reversed)) {
while (enumKeys.MoveNext()) {
++count;
}
}
return count;
}
}
}
///
/// Tests if the key is present in the part of the dictionary being viewed.
///
/// Key to check
/// True if the key is within this view.
public sealed override bool ContainsKey(TKey key)
{
if (!KeyInView(key))
return false;
else
return myDictionary.ContainsKey(key);
}
///
/// Tests if the key-value pair is present in the part of the dictionary being viewed.
///
/// Key to check for.
/// Value to check for.
/// True if the key-value pair is within this view.
public sealed override bool Contains(TKey key, TValue value)
{
if (!KeyInView(key))
return false;
else
return myDictionary.Contains(key, value);
}
///
/// Gets the number of values associated with a given key.
///
/// The key to count values of.
/// The number of values associated with . If
/// is not present in this view, zero is returned.
protected sealed override int CountValues(TKey key)
{
if (!KeyInView(key))
return 0;
else
return myDictionary.CountValues(key);
}
///
/// Adds the given key-value pair to the underlying dictionary of this view.
/// If is not within the range of this view, an
/// ArgumentException is thrown.
///
///
///
/// is not
/// within the range of this view.
public sealed override void Add(TKey key, TValue value)
{
if (!KeyInView(key))
throw new ArgumentException(Strings.OutOfViewRange, "key");
else
myDictionary.Add(key, value);
}
///
/// Removes the key (and associated value) from the underlying dictionary of this view. If
/// no key in the view is equal to the passed key, the dictionary and view are unchanged.
///
/// The key to remove.
/// True if the key was found and removed. False if the key was not found.
public sealed override bool Remove(TKey key)
{
if (!KeyInView(key))
return false;
else
return myDictionary.Remove(key);
}
///
/// Removes the key and value from the underlying dictionary of this view. that is equal to the passed in key. If
/// no key in the view is equal to the passed key, or has the given value associated with it, the dictionary and view are unchanged.
///
/// The key to remove.
/// The value to remove.
/// True if the key-value pair was found and removed. False if the key-value pair was not found.
public sealed override bool Remove(TKey key, TValue value)
{
if (!KeyInView(key))
return false;
else
return myDictionary.Remove(key, value);
}
///
/// Removes all the keys and values within this view from the underlying OrderedMultiDictionary.
///
/// The following removes all the keys that start with "A" from an OrderedMultiDictionary.
///
/// dictionary.Range("A", "B").Clear();
///
///
public sealed override void Clear()
{
if (entireTree) {
myDictionary.Clear();
}
else {
myDictionary.keyCount -= this.Count;
myDictionary.tree.DeleteRange(rangeTester);
}
}
///
/// Creates a new View that has the same keys and values as this, in the reversed order.
///
/// A new View that has the reversed order of this view.
public View Reversed()
{
return new View(myDictionary, rangeTester, entireTree, !reversed);
}
}
}
}