A small C# implementation of Semantic Versioning 2.0.0.
It provides a single immutable SemVer type for parsing, comparing, serializing, and
converting version strings of the form MAJOR.MINOR.PATCH[-PRERELEASE][+METADATA].
- Spec-compliant parsing. Parses
MAJOR.MINOR.PATCH[-PRERELEASE][+METADATA]using the official SemVer regex. - Correct precedence comparison. Release > pre-release, numeric identifiers (of any length) compared numerically and ranked below alphanumeric ones, longer pre-release wins on tie.
- Familiar BCL surface. Implements
ISpanParsable<SemVer>,IComparable<SemVer>, andIComparisonOperators<SemVer, SemVer, bool>. System.Text.Jsonsupport. Round-trips throughJsonSerializerout of the box, with no custom converter.- Implicit conversions. Converts to and from
string, plus interop withSystem.Version.
Install from NuGet:
dotnet add package Invex.SemanticVersionThe package targets .NET 10.0. It references JetBrains.Annotations, which NuGet restores automatically.
using Invex.SemanticVersion;
// Parse from a string
var version = SemVer.Parse("1.2.3-alpha.1+build.123");
Console.WriteLine(version.Major); // 1
Console.WriteLine(version.Minor); // 2
Console.WriteLine(version.Patch); // 3
Console.WriteLine(version.PreRelease); // alpha.1
Console.WriteLine(version.Metadata); // build.123
Console.WriteLine(version.Prefix); // 1.2.3
Console.WriteLine(version.IsPreRelease); // True
// Compare with natural operators
var stable = SemVer.Parse("2.0.0");
bool isNewer = stable > version; // True (release > pre-release)// Throws ArgumentException on invalid input
SemVer v = SemVer.Parse("1.0.0");
// Non-throwing variant
if (SemVer.TryParse("1.0.0-rc.1", out var parsed))
{
// use parsed
}
// ReadOnlySpan<char> overloads are also available (ISpanParsable<SemVer>)
SemVer fromSpan = SemVer.Parse("1.0.0".AsSpan(), null);See Parsing.
SemVer.Parse("1.0.0") > SemVer.Parse("1.0.0-alpha"); // True
SemVer.Parse("1.0.0-alpha.10") > SemVer.Parse("1.0.0-alpha.9"); // True (numeric)
SemVer.Parse("1.0.0-alpha.1.2") > SemVer.Parse("1.0.0-alpha.1"); // True (longer)
var list = new List<SemVer> { "2.0.0", "1.0.0", "1.0.0-rc.1" };
list.Sort(); // 1.0.0-rc.1, 1.0.0, 2.0.0Build metadata is used only as a final tiebreaker. See Comparison & Precedence.
var v = SemVer.Parse("1.5.0");
v.IsBetween("1.0.0", "2.0.0"); // True (exclusive bounds)
v.IsBetween("2.0.0", "1.0.0"); // True (bounds may be supplied in any order)
v.IsBetween("1.0.0", "1.5.0"); // False (upper bound is exclusive)See Range Checks.
SemVer version = "1.2.3"; // string -> SemVer
string text = version; // SemVer -> string ("1.2.3")
string json = JsonSerializer.Serialize(version); // System.Text.Json, no converter needed
Version sysVer = SemVer.Parse("3.2.1").ToSystemVersion(); // 3.2.1
SemVer fromSys = SemVer.FromSystemVersion(new Version(1, 2, 3));See String Conversion, JSON Serialization and System.Version Interop.
SemVer.Parse("1.0.0-rc.42").BuildNumberFromPreRelease; // 42
SemVer.Parse("1.0.0+build.99").BuildNumberFromMetadata; // 99
SemVer.ExtractBuildNumber("1.2.3"); // 0 (multiple numbers)Full documentation: https://invex-games.github.io/semantic-version/
| Guide | Contents |
|---|---|
| Introduction | When to use the library, key concepts and design principles |
| Getting Started | Installation and a five-minute quick start |
| Parsing | Parse, TryParse, span overloads and validation rules |
| Comparison & Precedence | CompareTo, operators and SemVer ordering rules |
| Range Checks | IsBetween: exclusive, order-independent ranges |
| String Conversion | Implicit string conversions and ToString |
| JSON Serialization | System.Text.Json round-trip support |
| System.Version Interop | Converting to and from System.Version |
| Build Number Extraction | BuildNumberFromPreRelease, BuildNumberFromMetadata, ExtractBuildNumber |
| Changelog | Release history |
| API Reference | Every public member |
The repository requires the .NET 10 SDK. From the repository root:
dotnet build Invex.SemanticVersion.slnx
dotnet test Invex.SemanticVersion.slnxThe _atom project is the DecSm.Atom build pipeline used to build, test, and
publish the package; it is not part of the published library. It also builds the DocFX site:
atom BuildDocs # build the site into _site/
atom ServeDocs # build and serve it locallyDistributed under the MIT License.