Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a standard class to represent a “range” in .net?

We have lots of code that has “min” and “max” values for things like prices, profit, costs etc. At present these are passed as two parameters to methods and often have different properties/methods to retrieve them.

I have seen a 101 custom classes to store ranges of values in different code bases over the past few decades, before I create yet another such class, I wish to confirm that the .NET framework these days don’t have such a class built in somewhere.

(I know how to create my own class if needed, but we have too many wheels in this world already for me to just invent anther one on a whim)

like image 278
Ian Ringrose Avatar asked Apr 16 '12 10:04

Ian Ringrose


2 Answers

AFAIK there is no such thing in .NET. Would be interesting though, to come up with a generic implementation.

Building a generic BCL quality range type is a lot of work, but it might look something like this:

public enum RangeBoundaryType
{
    Inclusive = 0,
    Exclusive
}

public struct Range<T> : IComparable<Range<T>>, IEquatable<Range<T>>
    where T : struct, IComparable<T>
{
    public Range(T min, T max) : 
        this(min, RangeBoundaryType.Inclusive, 
            max, RangeBoundaryType.Inclusive)
    {
    }

    public Range(T min, RangeBoundaryType minBoundary,
        T max, RangeBoundaryType maxBoundary)
    {
        this.Min = min;
        this.Max = max;
        this.MinBoundary = minBoundary;
        this.MaxBoundary = maxBoundary;
    }

    public T Min { get; private set; }
    public T Max { get; private set; }
    public RangeBoundaryType MinBoundary { get; private set; }
    public RangeBoundaryType MaxBoundary { get; private set; }

    public bool Contains(Range<T> other)
    {
        // TODO
    }

    public bool OverlapsWith(Range<T> other)
    {
        // TODO
    }

    public override string ToString()
    {
        return string.Format("Min: {0} {1}, Max: {2} {3}",
            this.Min, this.MinBoundary, this.Max, this.MaxBoundary);
    }

    public override int GetHashCode()
    {
        return this.Min.GetHashCode() << 256 ^ this.Max.GetHashCode();
    }

    public bool Equals(Range<T> other)
    {
        return
            this.Min.CompareTo(other.Min) == 0 &&
            this.Max.CompareTo(other.Max) == 0 &&
            this.MinBoundary == other.MinBoundary &&
            this.MaxBoundary == other.MaxBoundary;
    }

    public static bool operator ==(Range<T> left, Range<T> right)
    {
        return left.Equals(right);
    }

    public static bool operator !=(Range<T> left, Range<T> right)
    {
        return !left.Equals(right);
    }

    public int CompareTo(Range<T> other)
    {
        if (this.Min.CompareTo(other.Min) != 0)
        {
            return this.Min.CompareTo(other.Min);
        }

        if (this.Max.CompareTo(other.Max) != 0)
        {
            this.Max.CompareTo(other.Max);
        }

        if (this.MinBoundary != other.MinBoundary)
        {
            return this.MinBoundary.CompareTo(other.Min);
        }

        if (this.MaxBoundary != other.MaxBoundary)
        {
            return this.MaxBoundary.CompareTo(other.MaxBoundary);
        }

        return 0;
    }
}
like image 60
Steven Avatar answered Sep 29 '22 11:09

Steven


That's correct, before 2020, there was no built-in class in C# or the BCL for ranges. However, there is TimeSpan in the BCL for representing time spans, which you can compose additionally with a DateTime to represent a range of times.

like image 28
jason Avatar answered Sep 29 '22 11:09

jason