patterncsharpMinor
Custom struct design: Range
Viewed 0 times
customdesignstructrange
Problem
I had a need for some inventory management in a recent project. I decided to create a custom struct for managing the concept of a number range. It allows for easy navigation of a collection.
It function similar to .NET's own
The actual core struct class is:
A range lis
It function similar to .NET's own
Enumeration classes, with extension methods, wrapper classes and so forth allowing for dealing with a IRanged as defined:public interface IRanged
{
RangeType RangeType { get; }
T Start { get; }
T End { get; }
T Middle { get; }
int Size { get; }
T AtPercent(int percent);
T ValueAtIndex(int index, IRangedEdgeStrategy strategy);
}The actual core struct class is:
public struct Range : IEquatable, IRanged, IEnumerable
{
public Range(int start, int end)
{
if (start.Equals(end)) throw new ArgumentException("Cannot create a range of size zero");
if (start (int)Math.Round(((decimal)Start + End) / 2);
public int Size => Difference(Start, End);
public bool Contains(Range range)
{
return Start = range.End;
}
public static int Difference(int a, int b)
{
return Math.Abs(a - b) + 1;
}
public int ValueAtIndex(int index, IRangedEdgeStrategy strategy)
{
return strategy.Handle(this, index);
}
public int AtPercent(int percent)
{
if (percent 100)
throw new ArgumentOutOfRangeException("Percentage needs to be a integer value between 1 and 100");
var p = percent/100f*Size;
var clampedPercent = (int) Math.Round(p);
return AsClamped(clampedPercent);
}
public int AsClamped(int index)
{
return AsClamped(index, Start, End);
}
public static int AsClamped(int index, int start, int end)
{
return index end ? end : index;
}
#region IEnumerable
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator GetEnumerator()
{
for (var i = Start; i {End})"; }
}A range lis
Solution
Only targeting
-
If possible a struct should be immutable so you shouldn't let a user of this struct set the
-
pre calculate values in the constructor instead of calculating the values if accessed
-
always use braces
-
leave your operators some room to breathe.
would be more readable like
-
a ternary inside a ternary expression becomes almost unreadable.
This
would be more readable like
public struct Range -
If possible a struct should be immutable so you shouldn't let a user of this struct set the
RangeType property. -
pre calculate values in the constructor instead of calculating the values if accessed
public int Middle => (int)Math.Round(((decimal)Start + End) / 2);
public int Size => Difference(Start, End);-
always use braces
{} although they might be optional. Omitting braces can lead to serious bugs, using them will structure your code better and make you code more readable. -
leave your operators some room to breathe.
var p = percent/100f*Size;would be more readable like
var p = percent / 100f * Size;-
a ternary inside a ternary expression becomes almost unreadable.
This
public static int AsClamped(int index, int start, int end)
{
return index end ? end : index;
}would be more readable like
public static int AsClamped(int index, int start, int end)
{
if (index end ? end : index;
}Code Snippets
public int Middle => (int)Math.Round(((decimal)Start + End) / 2);
public int Size => Difference(Start, End);var p = percent/100f*Size;var p = percent / 100f * Size;public static int AsClamped(int index, int start, int end)
{
return index < start ? start : index > end ? end : index;
}public static int AsClamped(int index, int start, int end)
{
if (index < start)
{
return start;
}
return index > end ? end : index;
}Context
StackExchange Code Review Q#134816, answer score: 7
Revisions (0)
No revisions yet.