Created
March 23, 2021 10:04
-
-
Save mike-kilo/18ea3e997cf74c7a7945d82e2d530972 to your computer and use it in GitHub Desktop.
Range
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace Helpers | |
{ | |
public struct Range<T> where T : IComparable | |
{ | |
public T Start { get; set; } | |
public T End { get; set; } | |
private T GetMeasure() | |
{ | |
try | |
{ | |
return (T)Math.Abs((dynamic)this.End - (dynamic)this.Start); | |
} | |
catch (Exception e) | |
{ | |
throw new TypeAccessException($"'Range' struct of type '{typeof(T).FullName}' does not support range measure.", e); | |
} | |
} | |
/// <summary> | |
/// The measure of the range, including the starting limit. | |
/// </summary> | |
/// <remarks> | |
/// E.g. if the range is [3; 7], the Measure is 4 | |
/// </remarks> | |
public T Measure | |
{ | |
get | |
{ | |
return this.GetMeasure(); | |
} | |
} | |
public bool Contains(T value) | |
{ | |
try | |
{ | |
return (dynamic)value >= (dynamic)this.Start && (dynamic)value <= (dynamic)this.End; | |
} | |
catch (Exception e) | |
{ | |
throw new TypeAccessException($"'Range' struct of type '{typeof(T).FullName}' does not support value comparison.", e); | |
} | |
} | |
public static Range<T> operator* (Range<T> multiplier, T multiplicant) | |
{ | |
try | |
{ | |
return new Range<T> { Start = (dynamic)multiplier.Start * (dynamic)multiplicant, End = (dynamic)multiplier.End * (dynamic)multiplicant }; | |
} | |
catch (Exception e) | |
{ | |
throw new TypeAccessException($"'Range' struct of type '{typeof(T).FullName}' does not support multiplication.", e); | |
} | |
} | |
public static Range<T> operator /(Range<T> divident, T divisor) | |
{ | |
if ((dynamic)divisor == 0.0) throw new ArgumentException("Divide by zero? Please..."); | |
try | |
{ | |
return new Range<T> { Start = (dynamic)divident.Start / (dynamic)divisor, End = (dynamic)divident.End / (dynamic)divisor }; | |
} | |
catch (Exception e) | |
{ | |
throw new TypeAccessException($"'Range' struct of type '{typeof(T).FullName}' does not support division.", e); | |
} | |
} | |
public static Range<T> operator +(Range<T> summand1, T summand2) | |
{ | |
try | |
{ | |
return new Range<T> { Start = (dynamic)summand1.Start + (dynamic)summand2, End = (dynamic)summand1.End + (dynamic)summand2 }; | |
} | |
catch (Exception e) | |
{ | |
throw new TypeAccessException($"'Range' struct of type '{typeof(T).FullName}' does not support addition or the sum is outside of the range of '{typeof(T).FullName}'.", e); | |
} | |
} | |
public static Range<T> operator -(Range<T> minuend, T subtrahend) | |
{ | |
try | |
{ | |
return new Range<T> { Start = (dynamic)minuend.Start - (dynamic)subtrahend, End = (dynamic)minuend.End - (dynamic)subtrahend }; | |
} | |
catch (Exception e) | |
{ | |
throw new TypeAccessException($"'Range' struct of type '{typeof(T).FullName}' does not support subtraction or the difference is outside of the range of '{typeof(T).FullName}'.", e); | |
} | |
} | |
public static explicit operator Range<int>(Range<T> v) | |
{ | |
try | |
{ | |
return new Range<int> { Start = (int)(dynamic)v.Start, End = (int)(dynamic)v.End }; | |
} | |
catch (Exception e) | |
{ | |
throw new TypeAccessException($"'Range' struct of type '{typeof(T).FullName}' does not support casting to int.", e); | |
} | |
} | |
public static explicit operator Range<double>(Range<T> v) | |
{ | |
try | |
{ | |
return new Range<double> { Start = (double)(dynamic)v.Start, End = (double)(dynamic)v.End }; | |
} | |
catch (Exception e) | |
{ | |
throw new TypeAccessException($"'Range' struct of type '{typeof(T).FullName}' does not support casting to double.", e); | |
} | |
} | |
public static Range<T> Average(IEnumerable<Range<T>> ranges) | |
{ | |
try | |
{ | |
return ranges.Aggregate((a, b) => new Range<T> { Start = (dynamic)a.Start + (dynamic)b.Start, End = (dynamic)a.End + (dynamic)b.End }) / (dynamic)ranges.Count(); | |
} | |
catch (Exception e) | |
{ | |
throw new TypeAccessException($"'Range' struct of type '{typeof(T).FullName}' does not support averaging.", e); | |
} | |
} | |
public override bool Equals(object obj) | |
{ | |
return (obj is Range<T>) && | |
this.Start.Equals(((Range<T>)obj).Start) && | |
this.End.Equals(((Range<T>)obj).End); | |
} | |
public override int GetHashCode() | |
{ | |
return this.Start.GetHashCode() ^ this.End.GetHashCode(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment