Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7089499
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 28, 20262026-05-28T07:55:45+00:00 2026-05-28T07:55:45+00:00

How do I create a class to store a range of any type provided

  • 0

How do I create a class to store a range of any type provided that the type allows comparison operators to ensure that that the first value provided to the constructor is less than the second?

public class Range<T> where T : IComparable<T>
{
    private readonly T lowerBound;
    private readonly T upperBound;

    /// <summary>
    /// Initializes a new instance of the Range class
    /// </summary>
    /// <param name="lowerBound">The smaller number in the Range tuplet</param>
    /// <param name="upperBound">The larger number in the Range tuplet</param>
    public Range(T lowerBound, T upperBound)
    {
        if (lowerBound > upperBound)
        {
            throw new ArgumentException("lowerBlound must be less than upper bound", lowerBound.ToString());
        }

        this.lowerBound = lowerBound;
        this.upperBound = upperBound;            
    }

I am getting the error:

Error   1   Operator '>' cannot be applied to operands of type 'T' and 'T'  C:\Source\MLR_Rebates\DotNet\Load_MLR_REBATE_IBOR_INFO\Load_MLR_REBATE_IBOR_INFO\Range.cs   27  17  Load_MLR_REBATE_IBOR_INFO
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-28T07:55:45+00:00Added an answer on May 28, 2026 at 7:55 am

    To combine two suggestions already given, we combine the ability to create Ranges with a manually defined comparison rule, with an over-ride for those types that implement IComparable<T>, and with compile-time safety on the latter.

    We take much the same approach as the static Tuple class’ Create method. This can also offer concision in allowing us to rely upon type inference:

    public static class Range // just a class to a hold the factory methods
    {
        public static Range<T> Create<T>(T lower, T upper) where T : IComparable<T>
        {
            return new Range<T>(lower, upper, Comparer<T>.Default);
        }
        //We don't need this override, but it adds consistency that we can always
        //use Range.Create to create a range we want.
        public static Range<T> Create<T>(T lower, T upper, IComparer<T> cmp)
        {
            return new Range<T>(lower, upper, cmp);
        }
    }
    public class Range<T>
    {
        private readonly T lowerBound;
        private readonly T upperBound;
        private readonly IComparer<T> _cmp;
        public Range(T lower, T upper, IComparer<T> cmp)
        {
            if(lower == null)
                throw new ArgumentNullException("lower");
            if(upper == null)
                throw new ArgumentNullException("upper");
            if((_cmp = cmp).Compare(lower, upper) > 0)
                throw new ArgumentOutOfRangeException("Argument \"lower\" cannot be greater than \"upper\".");
            lowerBound = lower;
            upperBound = upper;
        }
    }
    

    Now we can’t accidentally construct a Range with the default comparer where it won’t work, but can also leave out the comparer and have it compile only if it’ll work.

    Edit:

    There are two main approaches to having items comparable in an order-giving way in .NET and this uses both.

    One way is to have a type define its on way of being compared with another object of the same type*. This is done by IComparable<T> (or the non-generic IComparable, but then you have to catch type mis-matches at run-time, so it isn’t as useful post .NET1.1).

    int for example, implements IComparable<int>, which means we can do 3.CompareTo(5) and receive a negative number indicating that 3 comes before 5 when the two are put into order.

    Another way is to have an object that implements IComparer<T> (and likewise a non-generic IComparer that is less useful post .NET1.1). This is used to compare two objects, generally of a different type to the comparer. We explicitly use this either because a type we are interested in doesn’t implement IComparable<T> or because we want to override the default sorting order. For example we could create the following class:

    public class EvenFirst : IComparer<int>
    {
      public int Compare(int x, int y)
      {
        int evenOddCmp = x % 2 - y % 2;
        if(evenOddCmp != 0)
          return evenOddCmp;
        return x.CompareTo(y);
      }
    }
    

    If we used this to sort a list of integers (list.Sort(new EvenFirst())), it would put all the even numbers first, and all the odd numbers last, but have the even and odd numbers in normal order within their block.

    Okay, so now we’ve got two different ways of comparing instances of a given type, one which is provided by the type itself and which is generally the “most natural”, which is great, and one which gives us more flexibility, which is also great. But this means that we will have to write two versions of any piece of code that cares about such comparisons – one that uses IComparable<T>.CompareTo() and one that uses IComparer<T>.Compare().

    It gets worse if we care about two types of objects. Then we need 4 different methods!

    The solution is provided by Comparer<T>.Default. This static property gives us an implementation of IComparer<T>.Compare() for a given T that calls into IComparable<T>.CompareTo.

    So, now we generally only ever write our methods to make use of IComparer<T>.Compare(). Providing a version that uses CompareTo for the most common sort of comparisons is just a matter of an override that uses the default comparer. E.g. instead of:

    public void SortStrings(IComparer<string> cmp)//lets caller decide about case-sensitivity etc.
    {
    //pretty complicated sorting code that uses cmp.Compare(string1, string2)
    }
    public void SortStrings()
    {
    //equally complicated sorting code that uses string.CompareTo()
    }
    

    We have:

    public void SortStrings(IComparer<string> cmp)//lets caller decide about case-sensitivity etc.
    {
    //pretty complicated sorting code that uses cmp.Compare(string1, string2)
    }
    public void SortStrings()
    {
      SortStrings(Comparer<string>.Default);//simple one-line code to re-use all the above.
    }
    

    As you can see, we’ve the best of both worlds here. Someone who just wants the default behaviour calls SortStrings(), someone who wants a more specific comparison rule to be used calls e.g. SortStrings(StringComparer.CurrentCultureIgnoreCase), and the implementation only had to do a tiny bit of work to offer that choice.

    This is what is done with the suggestion for Range here. The constructor always takes an IComparer<T> and always uses it’s Compare, but there’s a factory method that calls it with Comparer<T>.Default to offer the other behaviour.

    Note that we don’t strictly need this factory method, we can just use an overload on the constructor:

    public Range(T lower, T upper)
      :this(lower, upper, Comparer<T>.Default)
    {
    }
    

    The downside though, is that we can’t add a where clause to this to restrict it to cases where it’ll work. This means that if we called it with types that didn’t implement IComparer<T> we’d get an ArgumentException at runtime rather than a compiler error. Which was Jon’s point when he said:

    On the other hand, it does mean that you won’t catch incomparable types at compile time.

    The use of the factory method is purely to ensure this wouldn’t happen. Personally, I’d probably just go with the constructor override and try to be sure not to call it inappropriately, but I added the bit with the factory method since it does combine two things that had come up on this thread.

    *Strictly, there’s nothing to stop e.g. A : IComparable<B>, but while this is of little use in the first place, one also doesn’t know for most uses whether the code using it will end up calling a.CompareTo(b) or b.CompareTo(a) so it doesn’t work unless we do the same on both classes. In sort, if it can’t be pushed up to a common base-class it’s just going to get messy fast.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

OK so im trying to create a settings class to store certain strings that
I need to create class Dog and PurebredDog extending Dog. Problem is that Dog
I have a database that is similar to the following: create table Store(storeId) create
In principle, can I create a class library to store my Extension methods for
I've a name of a class stored in var, which I need to create
I create class libraries, some which are used by others around the world, and
How do I create class (i.e. static ) variables or methods in Python?
I have been curious about dynamically create class at runtime in C# and stumbled
I wonder, whether it is possible to create class-methods in VBA. By class-method I
I've found a task on some Java programming competition. One must create class Sentence

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.