I’ve recently decided to refresh my memory regarding C# basics, so this might be trivial, but i’ve bumped into the following issue:
StringCollection was used in .NET v1.0 in order to create a strongly typed collection for strings as opposed to an object based ArrayList (this was later enhanced by including Generic collections):
Taking a quick glance at StringCollection definition, you can see the following:
// Summary:
// Represents a collection of strings.
[Serializable]
public class StringCollection : IList, ICollection, IEnumerable
{
...
public int Add(string value);
...
}
You can see it implements IList, which contains the following declaration (among a few other declarations):
int Add(object value);
But not:
int Add(string value);
My first assumption was that it is possible due to the .NET framework covariance rules.
So just to make sure, I tried writing my own class which implements IList and changed
int Add(object value);
to retrieve a string type instead of an object type, but for my surprise, when trying to compile the project, I got an compile-time error:
does not implement interface member 'System.Collections.IList.Add(object)'
Any ideas what causes this?
Thanks!
The behavior is caused by the explicit implementation of
IList.Add(object)rather than co/contravariance. Per the MSDN documentation, StringCollection explicitly implementsIList.Add(object); theAdd(string)method is unrelated. The implementation may resemble something like this:This distinction can be observed:
Addendum
The above doesn’t address why this pattern is implemented. The C# language specification states that [§13.4.1, emphasis added]:
StringCollection adheres to the required IList behavior — IList makes no guarantee that any arbitrary object can be added to it. StringCollection makes stronger guarantees — primarily, that it will contain only strings. The class includes its own strongly-typed methods for
Add,Contains,Item, and others for the standard use case where it is accessed as aStringCollectionrather than anIList. But it still functions perfectly well as anIList, accepting and returning objects, but returning an error code (as IList permits) if an attempt is made to add an item that is not a string.Ultimately, whether an interface shows up in the class (i.e., is explicitly implemented) is at the discretion of the class author. In the case of framework classes, explicit implemenentations are included in the MSDN documentation but are not accessible as class members (e.g., shown in autocompletion contexts).