Nullable types and Interfaces

There has been some discussion( 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:


interface IElement<T>


    T Copy();

    bool IsEqual(T t);



class Collection<T>

    where T : IElement<T>


    public Collection<T> DeepCopy() {

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

        foreach (T element in this)




    public bool CompareElements(int indexA, int indexB) {

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



    public T this[int index]


        get { return elements[index]; }



    public void Add(T newElement) { }


    T[] elements;



struct Element : IElement<Element>


    public Element Copy() { }

    public bool 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():




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


I hope this helps.

Comments (9)

  1. AT says:

    hmm … You mixed so many language concepts here that this is hard to understand your motivation.

    You tell us that problem with generics restriction on Collection<Element?> must prevent nullable type Element? to implement all interfaces Element define ?

    This is no way related to original user suggestion.

    Yea. Element? will define all Element interfaces. But it will not define IElement<Element?> interface – so generics restriction still apply. Period.

    Take a look a little bit modified example:

    interface IElement<T>



    class MyClass : IElement<MyClass> {}

    class MyNullableClass : MyClass {

    bool IsNullable() { return thus==null; } // Please allow to call non-virtual methods on null instance (for structs – all methods are non-virtual !!).


    Now – then trying to use Collection<MyNullableClass> you will get the same limitation of _generics_.

    While there are nothing that prevent MyNullableClass to implement IElement<MyClass> interface.

    It looks you don’t get original idea.

    Then reffering to struct via interface – you are boxing it.

    Then boxing – you are trying to convert value-type to reference type.

    This is unreasonable to box nullable wrapper.

    You can box original object or use null reference based on nullable flag.

    Thus – you will have interface implemented – but it’s up to Microsoft to allow calling struct methods with this==null or nope.

    I’ve proposed possible options for this in report.

    Thanks for your attempt.

    Let’s reopen this discussion.

  2. Erno says:

    Perhaps I don’t understand you reasoning but when you state "For Element? to satisfy the constraint where where T : IElement<T>, it must implement IElement<Element?> not IElement<Element>." I can’t help but think: If an Element? inherits from Element it does satisfy the constraint. Maybe I didn’t get the point…

  3. aBlogByGus says:

    If the mixture of the word ‘nullable’, question marks, and C# are interesting to you then you you might want to check out the blogs of a couple of my peers: Peter (C# Compiler Dev lead) and Luca (C# Compiler…

  4. AT says:


    There is no covariance support for generics in current version of C# language (2.0)

    Microsoft quote from:

    "The fundamental issue is that B derives from A does not imply Gen<B> derives from Gen<A>. This is by design."

    Try to compile this:

    class ClassA {}

    class ClassB : ClassA {}

    interface IElement<T> {}

    class MyElement<T>: IElement<T> {} // Not critical – can be reduced to more simple contsruct without using interface

    void DoFoo() {

    IElement<ClassB> b = new MyElement<ClassB>();

    IElement<ClassA> a = (IElement<ClassA>) b; // Bingo – class cast exception here, support for IElement<ClassB> – does not mean that you support IElement<ClassA> !!!


    At the moment – CLR (but not a C# 2.0 lang) has some support for generics to follow original type params class hierarchy. (Corrrect me if this is wrong – I’ve not checked this myself and currently unable to find a link there I’ve read about this ).

    But the problem with your IElement example – is that type param T used on both sides – as "in" (method argument) and "out" (return value) for this interface. Your example is the only of one of reasons why generics does not follow class heirarchy at the moment.

    There are must be special type markers a T-, T+ to be able follow generics arguments class hierarchy in correct way.

    One more quote from FDBK17573

    "It looks like you are very interested in this feature. I think you will find usefull to take a read research paper related to this subject

    "Variant Parametric Types, A Flexible Subtyping Scheme for Generics" by Atsushi Igarashi and Mirko Viroli "

    Peter, Thanks for your time to construct such a complex example.

    I will reopen original report. Your arguments were not solid.