CLSS.Types.ValueRange 1.1.0

dotnet add package CLSS.Types.ValueRange --version 1.1.0
NuGet\Install-Package CLSS.Types.ValueRange -Version 1.1.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CLSS.Types.ValueRange" Version="1.1.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add CLSS.Types.ValueRange --version 1.1.0
#r "nuget: CLSS.Types.ValueRange, 1.1.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install CLSS.Types.ValueRange as a Cake Addin
#addin nuget:?package=CLSS.Types.ValueRange&version=1.1.0

// Install CLSS.Types.ValueRange as a Cake Tool
#tool nuget:?package=CLSS.Types.ValueRange&version=1.1.0

CLSS.Types.ValueRange

Problem

Structs can be used as dictionary keys. And a legitimate use case of structs as dictionary keys is to create branching code paths that can be changed at runtime as opposed to switch-case expression which necessarily requires hard-coding your code paths.

// You can't change these branching conditions at runtime
switch (responseCode)
{
  case int n when (200 <= n && n < 300):
    Path1();
    break;
  case int n when (300 <= n && n < 400):
    Path2();
    break;
  case int n when (400 <= n && n < 500):
    Path3();
    break;
}

// You can change these branching conditions at runtime
public struct IntRange { public int Min; public int Max; }
Dictionary<IntRange, Action> ResponseCodePaths = new Dictionary<IntRange, Action>()
{
  [new IntRange { Min = 200, Max = 300 }] = Path1,
  [new IntRange { Min = 300, Max = 400 }] = Path2,
  [new IntRange { Min = 400, Max = 500 }] = Path3
};
ResponseCodePaths.First(p => p.Key.Min <= responseCode < p.Key.Max)();
// add custom response code range at runtime
ResponseCodePaths[new IntRange { Min = 600, Max = 620 }] = Path4;

The default equality comparison of structs - which would be used by dictionaries when comparing keys - is not very performant, as .NET engineers themselves would readily tell you. In order to mitigate this performance issue, the struct type must implement the IEquatable<T> interface.

The fairly new ValueTuple type does this and also allows custom field names, but for the specific use case of value ranges, it is not type-safe. The types that ValueTuple accepts are not necessarily comparable types. ValueTuple is also not serializable - an attribute that's undoubtably valuable to Unity developers.

Solution

ValueRange is a type-safe, serializable generic struct type tailored to semantically represent a range of comparable values. The type of its Min and Max fields must satisfy an IComparable<T> constraint. If the constraint is not met, you will get a compilation error, ensuring that you will never get a runtime error if you use an uncomparable type in the type parameter.

ValueRange implements IEquatable<T> and therefore it's ready to be used as dictionary keys.

using System;

Dictionary<ValueRange<Version>, Action> VersionMigrationPaths = new Dictionary<ValueRange<Version>, Action>()
{
  [new ValueRange<Version>(Version.Parse("1.0"), Version.Parse("1.4"))] = Path1,
  [new ValueRange<Version>(Version.Parse("1.4"), Version.Parse("1.6"))] = Path2,
  [new ValueRange<Version>(Version.Parse("1.6"), Version.Parse("2.0"))] = Path3
};

Since version 1.1, this package also includes the Encapsulate extension method to grow a ValueRange to include more values. It can take in a params argument list of IComparable<T>s or other ValueRanges.

using CLSS;

var numbers = new int[] { 6, -11, -2, 4, 9 };
var numbersRange = new ValueRange<int>(numbers[0], numbers[0]);
numbersRange = numbersRange.Encapsulate(numbers); // Min: -11, Max: 9
var anotherRange1 = new ValueRange<int>(0, 16);
var anotherRange2 = new ValueRange<int>(-12, 0);
numbersRange = numbersRange.Encapsulate(anotherRange1, anotherRange2); // Min: -12, Max: 16
This package is a part of the C# Language Syntactic Sugar suite.
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on CLSS.Types.ValueRange:

Package Downloads
CLSS.ExtensionMethods.IComparable.InRange

An extension method to check whether the source value is within a range. A part of the C# Language Syntactic Sugar suite.

CLSS.ExtensionMethods.IComparable.ClampToRange

An extension method to clamp the source value into a range. A part of the C# Language Syntactic Sugar suite.

CLSS.Types.EventLatch

A synchronisation aid object for single-threaded context. A part of the C# Language Syntactic Sugar suite.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.1.0 239 2/16/2024
1.0.1 1,625 11/16/2022
1.0.0 2,550 8/1/2022

- Added Encapsulate extension method.