Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't Nullable<T> implement IComparable?

Tags:

.net

generics

The answer to this is probably glaringly obvious, but I'll stoop to asking anyway.

I was in the midst of writing a Range<T> class, and in the process realized I needed a comparer for it. So, I wrote a generic comparer, derived, naturally, from Comparer<T>:

public class Range<T> where T : IComparable
{

    // Simplified here for brevity -- actually uses the comparer
    public T Min { get; set; }

    // Simplified here for brevity -- actually uses the comparer
    public T Max { get; set; }

    private class DefaultComparer : Comparer<T> 
    {
        public override int Compare(T x, T y)
        {
            return x == null && y == null 
                ? 0 
                : x == null 
                    ? -1 
                    : y == null 
                        ? 1 
                        : x.CompareTo(y);
        }
    }
}

Now, this all works fine and well, until you pass a Nullable<T> as the type. For example:

public Range<DateTime?> DateSentFilter { get; set; }

This breaks horribly, because, of course, Nullable<T> doesn't implement IComparable. And this got me to thinking: Why not?

Given how a comparer is generally written, why couldn't it?

Does anyone with deep knowledge of this stuff have any idea? Is there a scenario that would prohibit this from being done?

like image 684
Mike Hofer Avatar asked Jan 29 '15 16:01

Mike Hofer


2 Answers

This is a comment from the source code:

// Warning, don't put System.Runtime.Serialization.On*Serializ*Attribute
// on this class without first fixing ObjectClone::InvokeVtsCallbacks
// Also, because we have special type system support that says a a boxed Nullable<T>
// can be used where a boxed<T> is use, Nullable<T> can not implement any intefaces
// at all (since T may not).   Do NOT add any interfaces to Nullable!
// 

As it says, Nullable<T> can't implement any interfaces for given reasons.

Now, the second question is: if it could, would they implement IComparable? No. Patrick has told why. Not every T implements IComparable, it just wouldn't make sense.

like image 184
Erti-Chris Eelmaa Avatar answered Sep 24 '22 12:09

Erti-Chris Eelmaa


Well, the generic type provided to Nullable<T> doesn't need to implement IComparable itself.

You have provided this condition yourself: T : IComparable, but that is not necessarily true for the T in Nullable<T>. I will agree that Nullable<T> is often used on primitive types that do implement IComparable but you could use it on structs, and they don't have IComparable implemented.

like image 27
Patrick Hofman Avatar answered Sep 25 '22 12:09

Patrick Hofman