Nullable types and Interfaces

Nullable types and Interfaces

There has been some discussion(http://lab.msdn.microsoft.com/ProductFeedback/viewFeedback.aspx?feedbackid=cdaf30a6-a601-43d7-8565-7096f82851ba) on whether T?, aka Nullable<T>, should implement the same interfaces as the underlying type T. At first glance, this seems reasonable enough – a T? is a little more than a T, so having T? implement the same interfaces as T should just fall right out.

Unfortunately, it is not that simple. Let’s consider this example to illustrate where the problems lie:

interfaceIElement<T>

{

T Copy();

bool IsEqual(T t);

}

classCollection<T>

where T : IElement<T>

{

publicCollection<T> DeepCopy() {

Collection<T> newCollection = newCollection<T>();

foreach (T element inthis)

newCollection.Add(element.Copy());

}

publicbool CompareElements(int indexA, int indexB) {

returnthis[indexA].IsEqual(this[indexB]);

}

public T this[int index]

{

get { return elements[index]; }

}

publicvoid Add(T newElement) { }

T[] elements;

}

structElement : IElement<Element>

{

publicElement Copy() { ... }

publicbool IsEqual(Element other) { ... }

}

The constraint where T : IElement<T> allows the DeepCopy and CompareElements methods to use the Copy and IsEqual methods on the elements in the collection. The Element struct implements IElement<Element> which satisfies the constraint, allowing it to be used with our container type as Collection<Element>.

Now if Element? implemented the same interfaces as Element, it should also be able to be used wherever Element is used, and we should be able to create a Collection<Element?>. Right? Not so fast. For Element? to satisfy the constraint where where T : IElement<T>, it must implement IElement<Element?>not IElement<Element>. You can see why this is by looking at this line in DeepCopy():

newCollection.Add(element.Copy());

The Copy() method must return the element type of the collection for this to type check.