DictionaryBase.cs :  » Development » TULP2G » Wintellect » PowerCollections » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Development » TULP2G 
TULP2G » Wintellect » PowerCollections » DictionaryBase.cs
//******************************
// Written by Peter Golde
// Copyright (c) 2004-2005, Wintellect
//
// Use and restribution of this code is subject to the license agreement 
// contained in the file "License.txt" accompanying this file.
//******************************

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;

namespace Wintellect.PowerCollections{
    /// <summary>
    /// DictionaryBase is a base class that can be used to more easily implement the
    /// generic IDictionary&lt;T&gt; and non-generic IDictionary interfaces.
    /// </summary>
    /// <remarks>
    /// <para>To use DictionaryBase as a base class, the derived class must override
    /// Count, GetEnumerator, TryGetValue, Clear, Remove, and the indexer set accessor. </para>
    /// </remarks>
    /// <typeparam name="TKey">The key type of the dictionary.</typeparam>
    /// <typeparam name="TValue">The value type of the dictionary.</typeparam>
    [Serializable]
    [DebuggerDisplay("{DebuggerDisplayString()}")]
    public abstract class DictionaryBase<TKey, TValue> : CollectionBase<KeyValuePair<TKey, TValue>>,
                                                                                                  IDictionary<TKey, TValue>, IDictionary
    {
        /// <summary>
        /// Creates a new DictionaryBase. 
        /// </summary>
        protected DictionaryBase()
        {
        }

        /// <summary>
        /// Clears the dictionary. This method must be overridden in the derived class.
        /// </summary>
        public abstract override void Clear();

        /// <summary>
        /// Removes a key from the dictionary. This method must be overridden in the derived class.
        /// </summary>
        /// <param name="key">Key to remove from the dictionary.</param>
        /// <returns>True if the key was found, false otherwise.</returns>
        public abstract bool Remove(TKey key);

        /// <summary>
        /// Determines if this dictionary contains a key equal to <paramref name="key"/>. If so, the value
        /// associated with that key is returned through the value parameter. This method must be
        /// overridden by the derived class.
        /// </summary>
        /// <param name="key">The key to search for.</param>
        /// <param name="value">Returns the value associated with key, if true was returned.</param>
        /// <returns>True if the dictionary contains key. False if the dictionary does not contain key.</returns>
        public abstract bool TryGetValue(TKey key, out TValue value);

        /// <summary>
        /// Adds a new key-value pair to the dictionary. 
        /// </summary>
        /// <remarks>The default implementation of this method
        /// checks to see if the key already exists using 
        /// ContainsKey, then calls the indexer setter if the key doesn't
        /// already exist. </remarks>
        /// <param name="key">Key to add.</param>
        /// <param name="value">Value to associated with the key.</param>
        /// <exception cref="ArgumentException">key is already present in the dictionary</exception>
        public virtual void Add(TKey key, TValue value)
        {
            if (ContainsKey(key)) {
                throw new ArgumentException(Strings.KeyAlreadyPresent, "key");
            }
            else {
                this[key] = value;
            }
        }

        /// <summary>
        /// Determines whether a given key is found
        /// in the dictionary.
        /// </summary>
        /// <remarks>The default implementation simply calls TryGetValue and returns
        /// what it returns.</remarks>
        /// <param name="key">Key to look for in the dictionary.</param>
        /// <returns>True if the key is present in the dictionary.</returns>
        public virtual bool ContainsKey(TKey key)
        {
            TValue dummy;
            return TryGetValue(key, out dummy);
        }

        /// <summary>
        /// The indexer of the dictionary. This is used to store keys and values and
        /// retrieve values from the dictionary. The setter
        /// accessor must be overridden in the derived class.
        /// </summary>
        /// <param name="key">Key to find in the dictionary.</param>
        /// <returns>The value associated with the key.</returns>
        /// <exception cref="KeyNotFoundException">Thrown from the get accessor if the key
        /// was not found in the dictionary.</exception>
        public virtual TValue this[TKey key] {
            get
            {
                TValue value;
                if (TryGetValue(key, out value))
                    return value;
                else
                    throw new KeyNotFoundException(Strings.KeyNotFound);
            }

            set
            {
                throw new NotImplementedException(Strings.MustOverrideIndexerSet);
            }
        }

        /// <summary>
        /// Shows the string representation of the dictionary. The string representation contains
        /// a list of the mappings in the dictionary.
        /// </summary>
        /// <returns>The string representation of the dictionary.</returns>
        public override string ToString()
        {
            bool firstItem = true;

            System.Text.StringBuilder builder = new System.Text.StringBuilder();

            builder.Append("{");

            // Call ToString on each item and put it in.
            foreach (KeyValuePair<TKey,TValue> pair in this) {
                if (!firstItem)
                    builder.Append(", ");

                if (pair.Key == null)
                    builder.Append("null");
                else
                    builder.Append(pair.Key.ToString());

                builder.Append("->");

                if (pair.Value == null)
                    builder.Append("null");
                else
                    builder.Append(pair.Value.ToString());

                firstItem = false;
            }

            builder.Append("}");
            return builder.ToString();
        }

        /// <summary>
        /// Provides a read-only view of this dictionary. The returned IDictionary&lt;TKey,TValue&gt; provides
        /// a view of the dictionary that prevents modifications to the dictionary. Use the method to provide
        /// access to the dictionary without allowing changes. Since the returned object is just a view,
        /// changes to the dictionary will be reflected in the view.
        /// </summary>
        /// <returns>An IIDictionary&lt;TKey,TValue&gt; that provides read-only access to the dictionary.</returns>
        public virtual new IDictionary<TKey,TValue> AsReadOnly()
        {
            return Algorithms.ReadOnly<TKey,TValue>(this);
        }



        #region IDictionary<TKey,TValue> Members

        /// <summary>
        /// Returns a collection of the keys in this dictionary. 
        /// </summary>
        /// <value>A read-only collection of the keys in this dictionary.</value>
        public virtual ICollection<TKey> Keys
        {
            get { return new KeysCollection(this); }
        }

        /// <summary>
        /// Returns a collection of the values in this dictionary. The ordering of 
        /// values in this collection is the same as that in the Keys collection.
        /// </summary>
        /// <value>A read-only collection of the values in this dictionary.</value>
        public virtual ICollection<TValue> Values
        {
            get { return new ValuesCollection(this); }
        }

        #endregion

        #region ICollection<KeyValuePair<TKey,TValue>> Members

        /// <summary>
        /// Adds a key-value pair to the collection. This implementation calls the Add method
        /// with the Key and Value from the item.
        /// </summary>
        /// <param name="item">A KeyValuePair contains the Key and Value to add.</param>
        public override void Add(KeyValuePair<TKey, TValue> item)
        {
            this.Add(item.Key, item.Value);
        }

        /// <summary>
        /// Determines if a dictionary contains a given KeyValuePair. This implementation checks to see if the
        /// dictionary contains the given key, and if the value associated with the key is equal to (via object.Equals)
        /// the value.
        /// </summary>
        /// <param name="item">A KeyValuePair containing the Key and Value to check for.</param>
        /// <returns></returns>
        public override bool Contains(KeyValuePair<TKey, TValue> item)
        {
            if (this.ContainsKey(item.Key)) {
                return (object.Equals(this[item.Key], item.Value));
            }
            else {
                return false;
            }
        }

        /// <summary>
        /// Determines if a dictionary contains a given KeyValuePair, and if so, removes it. This implementation checks to see if the
        /// dictionary contains the given key, and if the value associated with the key is equal to (via object.Equals)
        /// the value. If so, the key-value pair is removed.
        /// </summary>
        /// <param name="item">A KeyValuePair containing the Key and Value to check for.</param>
        /// <returns>True if the item was found and removed. False otherwise.</returns>
        public override bool Remove(KeyValuePair<TKey, TValue> item)
        {
            if (((ICollection<KeyValuePair<TKey, TValue>>)this).Contains(item))
                return this.Remove(item.Key);
            else
                return false;
        }

        #endregion

        #region IDictionary Members

        /// <summary>
        /// Check that the given parameter is of the expected generic type. Throw an ArgumentException
        /// if it isn't.
        /// </summary>
        /// <typeparam name="ExpectedType">Expected type of the parameter</typeparam>
        /// <param name="name">parameter name</param>
        /// <param name="value">parameter value</param>
        private void CheckGenericType<ExpectedType>(string name, object value)
        {
            if (!(value is ExpectedType))
                throw new ArgumentException(string.Format(Strings.WrongType, value, typeof(ExpectedType)), name);
        }

        /// <summary>
        /// Adds a key-value pair to the collection. If key or value are not of the expected types, an
        /// ArgumentException is thrown. If both key and value are of the expected types, the (overridden)
        /// Add method is called with the key and value to add.
        /// </summary>
        /// <param name="key">Key to add to the dictionary.</param>
        /// <param name="value">Value to add to the dictionary.</param>
        /// <exception cref="ArgumentException">key or value are not of the expected type for this dictionary.</exception>
        void IDictionary.Add(object key, object value)
        {
            CheckGenericType<TKey>("key", key);
            CheckGenericType<TValue>("value", value);
            Add((TKey)key, (TValue)value);
        }

        /// <summary>
        /// Clears this dictionary. Calls the (overridden) Clear method.
        /// </summary>
        void IDictionary.Clear()
        {
            this.Clear();
        }

        /// <summary>
        /// Determines if this dictionary contains a key equal to <paramref name="key"/>. The dictionary
        /// is not changed. Calls the (overridden) ContainsKey method. If key is not of the correct
        /// TKey for the dictionary, false is returned.
        /// </summary>
        /// <param name="key">The key to search for.</param>
        /// <returns>True if the dictionary contains key. False if the dictionary does not contain key.</returns>
        bool IDictionary.Contains(object key)
        {
            if (key is TKey || key == null)
                return ContainsKey((TKey)key);
            else
                return false;
        }

        /// <summary>
        /// Removes the key (and associated value) from the collection that is equal to the passed in key. If
        /// no key in the dictionary is equal to the passed key, the 
        /// dictionary is unchanged. Calls the (overridden) Remove method. If key is not of the correct
        /// TKey for the dictionary, the dictionary is unchanged.
        /// </summary>
        /// <param name="key">The key to remove.</param>
        /// <exception cref="ArgumentException">key could not be converted to TKey.</exception>
        void IDictionary.Remove(object key)
        {
            if (key is TKey || key == null)
                Remove((TKey)key);
        }

        /// <summary>
        /// Returns an enumerator that enumerates all the entries in the dictionary. Each entry is 
        /// returned as a DictionaryEntry.
        /// The entries are enumerated in the same orders as the (overridden) GetEnumerator
        /// method.
        /// </summary>
        /// <returns>An enumerator for enumerating all the elements in the OrderedDictionary.</returns>    
        IDictionaryEnumerator IDictionary.GetEnumerator()
        {
            // You can't implement this directly with an iterator, because iterators automatically implement
            // IEnumerator, not IDictionaryEnumerator. We use the helper class DictionaryEnumeratorWrapper.
            return new DictionaryEnumeratorWrapper(this.GetEnumerator());
        }

        /// <summary>
        /// Returns an enumerator that enumerates all the entries in the dictionary. Each entry is 
        /// returned as a DictionaryEntry.
        /// The entries are enumerated in the same orders as the (overridden) GetEnumerator
        /// method.
        /// </summary>
        /// <returns>An enumerator for enumerating all the elements in the OrderedDictionary.</returns>    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return ((IDictionary)this).GetEnumerator();
        }

        /// <summary>
        /// Returns whether this dictionary is fixed size. This implemented always returns false.
        /// </summary>
        /// <value>Always returns false.</value>
        bool IDictionary.IsFixedSize
        {
            get { return false; }
        }

        /// <summary>
        /// Returns if this dictionary is read-only. This implementation always returns false.
        /// </summary>
        /// <value>Always returns false.</value>
        bool IDictionary.IsReadOnly
        {
            get { return false; }
        }

        /// <summary>
        /// Returns a collection of all the keys in the dictionary. The values in this collection will
        /// be enumerated in the same order as the (overridden) GetEnumerator method.
        /// </summary>
        /// <value>The collection of keys.</value>
        ICollection IDictionary.Keys
        {
            get { return new KeysCollection(this); }
        }

        /// <summary>
        /// Returns a collection of all the values in the dictionary. The values in this collection will
        /// be enumerated in the same order as the (overridden) GetEnumerator method.
        /// </summary>
        /// <value>The collection of values.</value>
        ICollection IDictionary.Values
        {
            get { return new ValuesCollection(this); }
        }

        /// <summary>
        /// Gets or sets the value associated with a given key. When getting a value, if this
        /// key is not found in the collection, then null is returned. When setting
        /// a value, the value replaces any existing value in the dictionary. If either the key or value
        /// are not of the correct type for this dictionary, an ArgumentException is thrown.
        /// </summary>
        /// <value>The value associated with the key, or null if the key was not present.</value>
        /// <exception cref="ArgumentException">key could not be converted to TKey, or value could not be converted to TValue.</exception>
        object IDictionary.this[object key]
        {
            get
            {
                if (key is TKey || key == null) {
                    TKey theKey = (TKey)key;
                    TValue theValue;

                    // The IDictionary (non-generic) indexer returns null for not found, instead of
                    // throwing an exception like the generic IDictionary indexer.
                    if (TryGetValue(theKey, out theValue))
                        return theValue;
                    else
                        return null;
                }
                else {
                    return null;
                }
            }
            set
            {
                CheckGenericType<TKey>("key", key);
                CheckGenericType<TValue>("value", value);
                this[(TKey)key] = (TValue)value;
            }
        }

        #endregion

        /// <summary>
        /// Display the contents of the dictionary in the debugger. This is intentionally private, it is called
        /// only from the debugger due to the presence of the DebuggerDisplay attribute. It is similar
        /// format to ToString(), but is limited to 250-300 characters or so, so as not to overload the debugger.
        /// </summary>
        /// <returns>The string representation of the items in the collection, similar in format to ToString().</returns>
       new internal string DebuggerDisplayString()
       {
           const int MAXLENGTH = 250;

           bool firstItem = true;

            System.Text.StringBuilder builder = new System.Text.StringBuilder();

            builder.Append("{");

            // Call ToString on each item and put it in.
            foreach (KeyValuePair<TKey, TValue> pair in this) {
                if (builder.Length >= MAXLENGTH) {
                    builder.Append(", ...");
                    break;
                }

                if (!firstItem)
                    builder.Append(", ");

                if (pair.Key == null)
                    builder.Append("null");
                else
                    builder.Append(pair.Key.ToString());

                builder.Append("->");

                if (pair.Value == null)
                    builder.Append("null");
                else
                    builder.Append(pair.Value.ToString());

                firstItem = false;
            }

            builder.Append("}");
            return builder.ToString();
        }

        #region Keys and Values collections

        /// <summary>
        /// A private class that implements ICollection&lt;TKey&gt; and ICollection for the
        /// Keys collection. The collection is read-only.
        /// </summary>
        [Serializable]
        private sealed class KeysCollection : ReadOnlyCollectionBase<TKey>
        {
            private DictionaryBase<TKey, TValue> myDictionary;

            /// <summary>
            /// Constructor.
            /// </summary>
            /// <param name="myDictionary">The dictionary this is associated with.</param>
            public KeysCollection(DictionaryBase<TKey, TValue> myDictionary) 
            {
                this.myDictionary = myDictionary;
            }

            public override int Count
            {
                get { return myDictionary.Count; }
            }

            public override IEnumerator<TKey> GetEnumerator()
            {
                foreach (KeyValuePair<TKey, TValue> pair in myDictionary)
                    yield return pair.Key;
            }

            public override bool Contains(TKey key)
            {
                return myDictionary.ContainsKey(key);
            }
        }

        /// <summary>
        /// A private class that implements ICollection&lt;TValue&gt; and ICollection for the
        /// Values collection. The collection is read-only.
        /// </summary>
        [Serializable]
        private sealed class ValuesCollection : ReadOnlyCollectionBase<TValue>
        {
            private DictionaryBase<TKey, TValue> myDictionary;

            public ValuesCollection(DictionaryBase<TKey, TValue> myDictionary) 
            {
                this.myDictionary = myDictionary;
            }

            public override int Count
            {
                get { return myDictionary.Count; }
            }

            public override IEnumerator<TValue> GetEnumerator()
            {
                foreach (KeyValuePair<TKey, TValue> pair in myDictionary)
                    yield return pair.Value;
            }
        }

        #endregion

        /// <summary>
        /// A class that wraps a IDictionaryEnumerator around an IEnumerator that
        /// enumerates KeyValuePairs. This is useful in implementing IDictionary, because
        /// IEnumerator can be implemented with an iterator, but IDictionaryEnumerator cannot.
        /// </summary>
        [Serializable]
        private class DictionaryEnumeratorWrapper : IDictionaryEnumerator
        {
            private IEnumerator<KeyValuePair<TKey, TValue>> enumerator;

            /// <summary>
            /// Constructor.
            /// </summary>
            /// <param name="enumerator">The enumerator of KeyValuePairs that is being wrapped.</param>
            public DictionaryEnumeratorWrapper(IEnumerator<KeyValuePair<TKey, TValue>> enumerator)
            {
                this.enumerator = enumerator;
            }

            public DictionaryEntry Entry
            {
                get
                {
                    KeyValuePair<TKey, TValue> pair = enumerator.Current;
                    DictionaryEntry entry = new DictionaryEntry();
                    if (pair.Key != null)
                        entry.Key = pair.Key;
                    entry.Value = pair.Value;

                    return entry;
                }
            }

            public object Key
            {
                get
                {
                    KeyValuePair<TKey, TValue> pair = enumerator.Current;

                    return pair.Key;
                }
            }

            public object Value
            {
                get
                {
                    KeyValuePair<TKey, TValue> pair = enumerator.Current;
                    return pair.Value;
                }
            }

            public void Reset()
            {
                throw new NotSupportedException(Strings.ResetNotSupported);
            }


            public bool MoveNext()
            {
                return enumerator.MoveNext();
            }


            public object Current
            {
                get
                {
                    return Entry;
                }
            }
        }
    }
}


www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.