Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# - No implicit reference conversion from 'T' to 'System.IComparable<T>'

Tags:

c#

generics

I have taken the following class from another SO question:

    public class Range<T> where T : IComparable<T>
    {
        public T Minimum { get; set; }
        public T Maximum { get; set; }

        public override string ToString() { return String.Format("[{0} - {1}]", Minimum, Maximum); }

        public Boolean IsValid() { return Minimum.CompareTo(Maximum) <= 0; }

        public Boolean ContainsValue(T value)
        {
            return (Minimum.CompareTo(value) <= 0) && (value.CompareTo(Maximum) <= 0);
        }
    }

I would like, however, to create another class that contains many instances of this class, and can execute a foreach loop on them all, returning true if the number passed is contained in any one of the ranges:

    public class Ranges<T> where T : Range<T>
    {
        private List<Range<T>> rangelist;

        public void add(Range<T> range)
        {
            rangelist.Add(range);
        }

        public Boolean ContainsValue(T value)
        {
            foreach (Range<T> range in rangelist)
            {
                if (range.ContainsValue(value)) return true;
            }

            return false;
        }
    }

However, i am getting the error The type 'T' cannot be used as type parameter 'T' in the generic type or method 'Range<T>'. There is no implicit reference conversion from 'T' to 'System.IComparable<T>'.

What exactly is going wrong here?

like image 250
danbroooks Avatar asked Dec 01 '22 18:12

danbroooks


2 Answers

You don't seem to need the constraint where T : Range<T>

Just repeat the comparable constraint:

public class Ranges<T> where T : IComparable<T>
{
}
like image 66
Henk Holterman Avatar answered Dec 04 '22 07:12

Henk Holterman


If you rewrite your second class slightly, you'll see why:

public class Ranges<U> where U : Range<U>
{
    private List<Range<U>> rangelist;

    public void add(Range<U> range)
    {
        rangelist.Add(range);
    }
    ...
}

The error is telling you the compiler does not know if U is convertible to IComparable<U>, which is apparent from the declaration of Ranges<U> and Range<T> (Range<T> does not implement any interfaces).

More importantly, you have a recursing generic argument!

If U is Range<U>, then your class looks like Ranges<Range<T>> where T is U, and so on and so forth.

From what I can tell, you're not looking to write:

Ranges<Range<int>> x = ...;

But rather:

Ranges<int> x = ...;

Which would mean:

public class Ranges<T> where T : IComparable<T>
{
    private List<Range<T>> rangelist;

    ...
like image 20
user7116 Avatar answered Dec 04 '22 09:12

user7116