Search code examples
.net.net-3.0inotifycollectionchanged

Why is there no ObservableKeyedCollection<TKey, TValue> in the .NET Framework?


The .NET Framework contains since version 3.0 the ObservableCollection<T>, but why isn´t there a ObservableKeyedCollection<TKey, TValue>.

Okay i could implement my own collection by deriving from KeyedCollection<TKey,TValue> and implementing the INotifyCollectionChanged interface, but whouldn´t it be a good addition to the .NET Framework.


Solution

  • The reason that there is no ObservableKeyedCollection (or any other such type which is merely a combination of other generic types) is because ObservableCollection is generic, and that makes implementation of an "ObservableKeyedCollection" as easy as this:

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    
    public class DictionaryWatcher : ObservableCollection<KeyValuePair<string, object>>, IDisposable
    {
        private NotifyCollectionChangedEventHandler watcher;
        private bool watching = false;
    
        public DictionaryWatcher()
        {
            watcher = new NotifyCollectionChangedEventHandler( ReportChange );
            CollectionChanged += watcher;
            Watched = true;
        }
    
        public bool Watched
        {
            get
            {
                return watching;
            }
    
            set
            {
                if (watching)
                {
                    lock (this)
                    {
                        CollectionChanged -= watcher;
                        watching = false;
                    }
                }
            }
        }
    
    public void Dispose()
    {
        Dispose( true );
        GC.SuppressFinalize( this );
    }
    
        public void Initialize()
        {
            this.Add( new KeyValuePair<string, object>( "First", 1 ) );
            this.Add( new KeyValuePair<string, object>( "Second", 2 ) );
            this.Add( new KeyValuePair<string, object>( "Turd", 3 ) );
            KeyValuePair<string, object> badValue = this[2];
            this.Remove( badValue );
        }
    
    protected virtual void Dispose( bool disposing )
    {
        if (disposing && Watched)
        {
            Watched = false;
        }
    }
    
        private void ReportChange( object sender, NotifyCollectionChangedEventArgs e )
        {
            Console.WriteLine( "Change made: {0}", e.Action );
        }
    }
    

    While that is certainly not a one-liner program, most of it is boilerplate. Most importantly, it doesn't re-implement the ObservableCollection as you were suggesting; instead it fully utilizes it.

    The reason that it "whouldn't be a good addition to the .NET Framework" is because when there's already one way to do something, creating another way to do it is a bad idea. The fewer ways there are to get some particular task done, the fewer ways there are to do it poorly. 8 )

    The tools are provided, it's now all about how you use them.

    Hope that helps!