Arsalan's Musings on Software

Software design and development techniques, ideas, and source code snippets…

Creating an unmodifiable list from a regular old IList

leave a comment »

Your Mission

Create an unmodifiable list utility class that converts any implementation of IList interface into a list that throws exception when modified.  Take into consideration converting implementations of ArrayList<T>.
Give examples of useful usages of such utility class (does not have to be in code).

Do you accept this mission?

Hmmm… let’s see.


Why would anyone want to use a list that cannot be modified?

Consider the following scenarios.
1. Sending an Employee list to an accounting system using RPC, ensuring the list cannot be changed. In such a case, a class can be passed to the Sealed list constructor to get a sealed class and passed on to the remote system.

2. If the list is bound to a control on a Web Form or Windows Form and the control has edit functionality, if the user edits the form and the list could be modified, the sealed list class can be used.

3. A deck of cards [fixed number of items] should not allow addition of other cards in a card game.

There maybe many such cases where you want the collection to stay as-is.


Design

Let’s design the solution using the Decorator design pattern. The decorator pattern is quite fascinating as it creates a paradigm of wrapping increasingly specialized behavior to objects while keeping their base type uniform. Hence, one type decorates another and effectively changes the behavior without modifying existing code. Superb!

Wikipedia has this nice diagram describing our Decorator pattern:
Decorator Pattern


We will start creating our SealedList class as follows.

private IList list;
private const string exceptionMessage = "List cannot be modified.";

public SealedList(IList list)
{
this.list = list;
}

We will make sure that our custom class implements the IList interface. We will not need to implement all the required methods in IList simply throwing a NotImplementedException for methods not implemented. We can always implement them later, if needed. Here are the IList methods.

public int Add(object value)
{
throw new InvalidOperationException(exceptionMessage);
}

public void Clear()
{
throw new InvalidOperationException(exceptionMessage);
}

public bool Contains(object value)
{
return list.Contains(value);
}

public int IndexOf(object value)
{
return list.IndexOf(value);
}

public void Insert(int index, object value)
{
throw new InvalidOperationException(exceptionMessage);
}

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

public bool IsReadOnly
{
get
{
return list.IsReadOnly;
}
}

public void Remove(object value)
{
throw new InvalidOperationException(exceptionMessage);
}

public void RemoveAt(int index)
{
throw new InvalidOperationException(exceptionMessage);
}

public object this[int index]
{
get
{
return list[index];
}
set
{
throw new InvalidOperationException(exceptionMessage);
}
}

Since the IList interface itself implements the ICollection and IEnumerable interfaces, we have to implement methods required by those interfaces as well.

#region ICollection Members

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

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

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

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

#endregion

#region IEnumerable Members

public IEnumerator GetEnumerator()
{
return list.GetEnumerator();
}

#endregion

That should do it as far as creating the sealed list is concerned. But we still haven’t verified that this works correctly. For that, we will have to create an unsealed list and then try to seal it by decorating it with our SealedList and unit test the heck out of it… stay tuned for the exciting conclusion in the next post!

Advertisements

Written by Arsalan A.

July 7, 2009 at 10:50 am

Posted in 1

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: