//******************************************************************************************************
// DictionaryList.cs - Gbtc
//
// Copyright © 2012, Grid Protection Alliance. All Rights Reserved.
//
// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
// the NOTICE file distributed with this work for additional information regarding copyright ownership.
// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may
// not use this file except in compliance with the License. You may obtain a copy of the License at:
//
// http://www.opensource.org/licenses/MIT
//
// Unless agreed to in writing, the subject software distributed under the License is distributed on an
// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
// License for the specific language governing permissions and limitations.
//
// Code Modification History:
// ----------------------------------------------------------------------------------------------------
// 01/07/2006 - J. Ritchie Carroll
// Generated original version of source code.
// 09/10/2008 - J. Ritchie Carroll
// Converted to C#.
// 02/19/2009 - Josh L. Patterson
// Edited Code Comments.
// 08/05/2009 - Josh L. Patterson
// Edited Comments.
// 09/14/2009 - Stephen C. Wills
// Added new header and license agreement.
// 12/13/2012 - Starlynn Danyelle Gilliam
// Modified Header.
//
//******************************************************************************************************
using System.Collections;
using System.Collections.Generic;
namespace GSF.Collections
{
///
/// Represents a sorted dictionary style list that supports .
///
///
///
/// Have you ever needed the quick look-up feature on a Dictionary (e.g., Hashtable), but ended
/// up missing the indexed or sequential access like you have in a list? You may have wondered why
/// the .NET dictionary class doesn’t implement the IList interface which allows this. The reason
/// IDictionary implementations do not normally implement the IList interface is because of
/// ambiguity that is caused when implementing an integer key. For example, if you created a
/// dictionary style class with a key of type "Integer" that actually did implement IList(Of T),
/// you would not be able to access items in the IList interface by index without "casting" the
/// class as IList. This is because the Item property in both the IDictionary and IList would have
/// the same parameters. Note, however, that generics in .NET 2.0 gladly allow a class to implement
/// both IDictionary and IList (even specifying as Integer as the key) so long you as you are happy
/// knowing that the compiler will choose if you access your items by index or key. Given that
/// caveat, there are many times when you need a dictionary style collection but also desire an
/// IList implementation so the class can be used in other ways without conversion. As a result of
/// these needs, we’ve added a generic class to code library called a DictionaryList -- which is
/// essentially just a sorted dictionary style list (i.e., SortedList) that implements the
/// IList(Of T) interface (specifically as IList(Of KeyValuePair(Of TKey, TValue))). You will find
/// all of your convenient expected methods related to both dictionaries and lists; that is, you can
/// look-up items by key or by index. The class works perfectly for any non-Integer based key
/// (e.g., String, custom class, etc.) -- note that specifying an Integer as the key for the class
/// won’t cause an error, but it also will not be very useful. However, you can specify the key for
/// your DictionaryList as a "Long," which allows you to use long integers for keyed look-ups and
/// regular integers for indexed access--the best of both worlds! In summary, I would not change
/// your programming habits to start using this for "my collection for everything," as nothing comes
/// for free; however, if you have a need for a "hybrid" collection class, this fits the bill.
///
///
/// Important note about using an "Integer" as the key for this class: IDictionary implementations
/// do not normally implement the IList interface because of ambiguity that is caused when implementing
/// an integer key. For example, if you implement this class with a key of type "Integer" you will not
/// be able to access items in the queue by index without "casting" the class as IList. This is because
/// the Item property in both the IDictionary and IList would have the same parameters.
///
///
/// Note that prior to the addition of Generics in .NET, the class that performed a similar function
/// was the "NameObjectCollectionBase" in the System.Collections.Specialized namespace which
/// specifically allowed item access by either key or by index. This class is similar in function
/// but instead is a generic class allowing use with any strongly typed key or value.
///
///
/// Generic key type.
/// Generic value type.
public class DictionaryList : IList>, IDictionary
{
#region [ Members ]
// Fields
private readonly SortedList m_list;
#endregion
#region [ Constructors ]
///
/// Creates a new .
///
public DictionaryList()
{
m_list = new SortedList();
}
#endregion
#region [ Properties ]
// Generic IList(Of KeyValuePair(Of TKey, TValue)) Properties
///
/// Gets the number of elements contained in the .
///
public int Count
{
get
{
return m_list.Count;
}
}
///
/// Gets a value indicating whether the is read-only.
///
public bool IsReadOnly
{
get
{
return false;
}
}
///
/// Gets or sets the element at the specified index.
///
/// The zero-based index of the element to get or set.
/// The element at the specified index.
public KeyValuePair this[int index]
{
get
{
return new KeyValuePair(m_list.Keys[index], m_list.Values[index]);
}
set
{
m_list[value.Key] = value.Value;
}
}
// Generic IDictionary(Of TKey, TValue) Properties
///
/// Gets or sets the element with the specified key.
///
/// The key of the element to get or set.
/// The element with the specified key.
public TValue this[TKey key]
{
get
{
return m_list[key];
}
set
{
m_list[key] = value;
}
}
///
/// Gets an containing the keys of the .
///
public ICollection Keys
{
get
{
return m_list.Keys;
}
}
///
/// Gets an containing the values in the .
///
public ICollection Values
{
get
{
return m_list.Values;
}
}
#endregion
#region [ Methods ]
// Generic IList(Of KeyValuePair(Of TKey, TValue)) Methods
///
/// Adds an item to the .
///
/// The key value pair item to add.
public void Add(KeyValuePair item)
{
m_list.Add(item.Key, item.Value);
}
///
/// Removes all items from the .
///
public void Clear()
{
m_list.Clear();
}
///
/// Determines whether the contains a specific value.
///
/// The object to locate in the .
/// true if item is found in the ; otherwise, false
public bool Contains(KeyValuePair item)
{
return m_list.ContainsKey(item.Key);
}
///
/// Copies the elements of the to an , starting at a particular index.
///
///
/// The one-dimensional that is the destination of the elements
/// copied from . The array must
/// have zero-based indexing.
///
/// The zero-based index in array at which copying begins.
public void CopyTo(KeyValuePair[] array, int arrayIndex)
{
for (int x = 0; x < m_list.Count; x++)
{
array[arrayIndex + x] = new KeyValuePair(m_list.Keys[x], m_list.Values[x]);
}
}
///
/// 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 bool Remove(KeyValuePair item)
{
return m_list.Remove(item.Key);
}
///
/// Determines the index of a specific item in the .
///
/// The object to locate in the .
/// The index of item if found in the list; otherwise, -1.
public int IndexOf(KeyValuePair item)
{
return m_list.IndexOfKey(item.Key);
}
///
/// Removes the item at the specified index.
///
/// The zero-based index of the item to remove.
public void RemoveAt(int index)
{
m_list.RemoveAt(index);
}
///
/// Inserts an item to the at the specified index.
///
/// The zero-based index at which item should be inserted.
/// The object to insert into the .
public void Insert(int index, KeyValuePair item)
{
// It does not matter where you try to insert the value, since it will be inserted into its sorted
// location, so we just add the value.
m_list.Add(item.Key, item.Value);
}
///
/// Returns an enumerator that iterates through the collection.
///
/// A that can be used to iterate through the collection.
public IEnumerator> GetEnumerator()
{
return m_list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)m_list).GetEnumerator();
}
// Generic IDictionary(Of TKey, TValue) Methods
///
/// Adds an element with the provided key and value to the .
///
/// The object to use as the key of the element to add.
/// The object to use as the value of the element to add.
public void Add(TKey key, TValue value)
{
m_list.Add(key, value);
}
///
/// Determines whether the contains an element with the specified key.
///
/// The key to locate in the .
/// true if the contains an element with the key; otherwise, false.
public bool ContainsKey(TKey key)
{
return m_list.ContainsKey(key);
}
///
/// Determines whether the contains a specific value.
///
/// The value to locate in the . The value can be null for reference types.
/// true if the contains an element with the specified value; otherwise, false.
public bool ContainsValue(TValue value)
{
return m_list.ContainsValue(value);
}
///
/// Searches for the specified key and returns the zero-based index within the entire .
///
/// The key to locate in the .
/// The zero-based index of key within the entire , if found; otherwise, -1.
public int IndexOfKey(TKey key)
{
return m_list.IndexOfKey(key);
}
///
/// Searches for the specified value and returns the zero-based index of the first occurrence within the entire .
///
/// The value to locate in the . The value can be null for reference types.
/// The zero-based index of the first occurrence of value within the entire , if found; otherwise, -1.
public int IndexOfValue(TValue value)
{
return m_list.IndexOfValue(value);
}
///
/// Removes the element with the specified key from the .
///
/// The key of the element to remove.
///
/// true if the element is successfully removed; otherwise, false. This method also returns false if key
/// was not found in the original .
public bool Remove(TKey key)
{
return m_list.Remove(key);
}
///
/// Gets the value associated with the specified key.
///
/// The key whose value to get.
///
/// When this method returns, the value associated with the specified key, if
/// the key is found; otherwise, the default value for the type of the value
/// parameter. This parameter is passed uninitialized.
///
/// true if the contains an element with the specified key; otherwise, false.
public bool TryGetValue(TKey key, out TValue value)
{
return m_list.TryGetValue(key, out value);
}
#endregion
}
}