A read-only IDictionary wrapper for .Net 1/1.1

November 24, 2004

How to disable write operations on a given IDictionary instance (specifically, a Hashtable instance)? Until now I couldn’t find an immediate answer in .Net framework 1.0/1.1.

This feature seems to be discussed and addressed in .Net 2.0, but I’m targeting .Net 1.0/1.1. I finally ended up writing a decorator a-la ArrayList.ReadOnly().

Hashtable table = new Hashtable();
table.Add("key", "value");
IDictionary readOnlyTable = ReadOnlyDictionary.ReadOnly(table);
try
{
    readOnlyTable.Add("anotherkey", "anothervalue");
}
catch (NotSupportedException)
{
    // this exception will be thrown
}

The wrapper code:

using System;
using System.Collections;

namespace DotNetGuru.Collections
{
    public class ReadOnlyDictionary : IDictionary
    {
        private IDictionary _originalDictionary;

        private ReadOnlyDictionary(IDictionary original)
        {
            _originalDictionary = original;
        }

        public static ReadOnlyDictionary ReadOnly(
            IDictionary dictionary)
        {
            return new ReadOnlyDictionary(dictionary);    
        }

        private void ReportNotSupported()
        {
            throw new NotSupportedException(
                "Collection is read-only.");
        }

        public bool IsReadOnly { get { return true; } }

        public IDictionaryEnumerator GetEnumerator()
        {
            return _originalDictionary.GetEnumerator();
        }

        public object this[object key]
        {
            get { return _originalDictionary[key]; }
            set { ReportNotSupported(); }
        }

        public void Remove(object key)
        {
            ReportNotSupported();
        }

        public bool Contains(object key)
        {
            return _originalDictionary.Contains(key);
        }

        public void Clear() { ReportNotSupported(); }

        public ICollection Values
        {
            get { return _originalDictionary.Values; }
        }

        public void Add(object key, object value)
        {
            ReportNotSupported();
        }

        public ICollection Keys
        {
            get { return _originalDictionary.Keys; }
        }

        public bool IsFixedSize
        {
            get { return _originalDictionary.IsFixedSize; }
        }

        public void CopyTo(Array array, int index)
        {
            _originalDictionary.CopyTo(array, index);
        }

        public int Count
        {
            get { return _originalDictionary.Count; }
        }

        public object SyncRoot
        {
            get { return _originalDictionary.SyncRoot; }
        }

        public bool IsSynchronized
        {
            get
            {
                return _originalDictionary.IsSynchronized;
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return _originalDictionary.GetEnumerator();
        }
    }
}