2

How is it possible for ReadOnlyCollection to implement IList? The latter requires implementation of the Add method, and the ReadOnlyCollection does not implement this. However, ReadOnlyCollection is concrete and can be instantiated...

Edit

The following code will not compile on my machine:

static void Main(string[] args)
{
    List<string> people = new List<string>(){
        "Sidney",
        "Jim",
        "Bob"};

    ReadOnlyCollection<string> readOnlyPeople = new ReadOnlyCollection<string>(people);
    readOnlyPeople.Add("Frank");
}

The call to "Add" in the last statement is now underlined in blue in Visual Studio 2010.

Andrew
  • 6,144
  • 10
  • 37
  • 54
  • 1
    That code won't compile because the `Add` method is _explicitly_ implemented. You have to cast to `IList` before you can access it. – Paul Phillips Aug 29 '11 at 02:28
  • I'm still confused. Where is it 'explicitly' implemented? I thought interfaces didn't support implementations of methods... – Andrew Aug 29 '11 at 02:34
  • 1
    You're right that interfaces don't themselves implement the method. Explicit implementation is a special thing in C# - [see this answer for more info](http://stackoverflow.com/questions/143405/c-interfaces-implicit-and-explicit-implementation). – Paul Phillips Aug 29 '11 at 02:38
  • Sorry, thanks Paul. I just googled explicit implementation and interfaces. Thanks for mentioning it! – Andrew Aug 29 '11 at 02:39

2 Answers2

4

It does implement Add, the implementation simply throws a NotSupportedException.

The implementation uses "explicit interface implementation", which is a way of implementing interfaces without directly exposing interface methods as public on the implementing class. It's most useful when you have a class that implements more than one interface that defines the same member (see the example at the link). Basically, it looks something like this:

public interface IList<T>
{
    int Add(object value);
    // and a whole bunch of other stuff...
}

public class ReadOnlyCollection<T> : IList<T>
{
    int IList<T>.Add(object value)
    {
        throw new NotSupportedException();
    }
}

Notice how the add method isn't public, so if you have an instance of ReadOnlyCollection<T>, you can't directly call Add on it. What you can do however, if you want to see the exception, is cast your instance to the interface:

ReadOnlyCollection<string> readOnlyPeople = new ReadOnlyCollection<string>(people);
((IList<string>)readonlyPeople).Add("Frank"); // <-- bang!

The other way you could achieve it is to declare your variable as an IList<T> directly:

IList<string> readOnlyPeople = new ReadOnlyCollection<string>(people);
readOnlyPeople.Add("Frank"); // <-- this should go 'bang!' too
Jon
  • 16,212
  • 8
  • 50
  • 62
1

It does implement the Add method, but the implementation of that method just throws a NotSupportedException.

TrueWill
  • 25,132
  • 10
  • 101
  • 150