Repository navigation
Semantic Versions
The following sections provide a more detailed look at the SemanticVersion class.
Create a semantic version directly using the constructor:
using Enbrea.SemVer;
var version = new SemanticVersion(1, 2, 3);With a prerelease label:
var version = new SemanticVersion(1, 2, 3, "beta");With prerelease information and build metadata:
var version = new SemanticVersion(1, 2, 3, "rc.1", "build.42");Build metadata can also be supplied without prerelease information:
var version = new SemanticVersion(1, 2, 3, buildMetadata: "build.42");Major, minor, and patch numbers must be non-negative. Prerelease and build metadata values are validated according to the Semantic Versioning 2.0.0 rules.
Use SemanticVersion.Parse() to parse Semantic Versioning 2.0.0 strings:
var release = SemanticVersion.Parse("1.2.3");
var prerelease = SemanticVersion.Parse("1.2.3-beta");
var build = SemanticVersion.Parse("1.2.3+build.42");
var complete = SemanticVersion.Parse("1.2.3-rc.1+build.42");Parse is also available for ReadOnlySpan<char>:
ReadOnlySpan<char> value = "1.2.3-beta.1";
var version = SemanticVersion.Parse(value);When parsing input that may be invalid, use TryParse() to avoid exceptions:
if (SemanticVersion.TryParse("1.2.3", out var version))
{
Console.WriteLine(version);
}TryParse also supports ReadOnlySpan<char>:
ReadOnlySpan<char> value = "1.2.3-beta.1";
if (SemanticVersion.TryParse(value, out var version))
{
Console.WriteLine(version);
}Important
Parsing is strict and follows the Semantic Versioning 2.0.0 specification. Versions such as 1, 1.2, 01.2.3, or 1.2.3-alpha.01 are rejected.
Use SemanticVersion.IsValid() when you only need to determine whether a value represents a valid semantic version:
Console.WriteLine(SemanticVersion.IsValid("1.2.3")); // True
Console.WriteLine(SemanticVersion.IsValid("1.2.3-alpha.1+build.42")); // True
Console.WriteLine(SemanticVersion.IsValid("1.2")); // False
Console.WriteLine(SemanticVersion.IsValid("01.2.3")); // FalseA ReadOnlySpan<char> overload is also available:
ReadOnlySpan<char> value = "2.0.0";
Console.WriteLine(SemanticVersion.IsValid(value)); // TrueA semantic version consists of the following components:
| Property | Description |
|---|---|
Major |
Major version number |
Minor |
Minor version number |
Patch |
Patch version number |
PreRelease |
Optional prerelease identifiers |
BuildMetadata |
Optional build metadata |
IsPrerelease |
Indicates whether prerelease information is present |
HasBuildMetadata |
Indicates whether build metadata is present |
Example:
var version = SemanticVersion.Parse("1.2.3-alpha.1+build.42");
Console.WriteLine(version.Major); // 1
Console.WriteLine(version.Minor); // 2
Console.WriteLine(version.Patch); // 3
Console.WriteLine(version.PreRelease); // alpha.1
Console.WriteLine(version.BuildMetadata); // build.42
Console.WriteLine(version.IsPrerelease); // True
Console.WriteLine(version.HasBuildMetadata); // TrueSemanticVersion is immutable. Use the With... methods to create a version with an updated component:
var version = SemanticVersion.Parse("1.2.3-alpha+build.9");
var newMajor = version.WithMajor(2);
var newMinor = version.WithMinor(5);
var newPatch = version.WithPatch(7);
Console.WriteLine(newMajor); // 2.2.3-alpha+build.9
Console.WriteLine(newMinor); // 1.5.3-alpha+build.9
Console.WriteLine(newPatch); // 1.2.7-alpha+build.9Prerelease information and build metadata can also be changed:
var version = SemanticVersion.Parse("1.2.3");
var prerelease = version.WithPreRelease("beta.1");
var withBuild = prerelease.WithBuildMetadata("build.42");
Console.WriteLine(prerelease); // 1.2.3-beta.1
Console.WriteLine(withBuild); // 1.2.3-beta.1+build.42Use WithoutPreRelease() and WithoutBuildMetadata() to remove optional components:
var version = SemanticVersion.Parse("1.2.3-rc.1+build.42");
Console.WriteLine(version.WithoutPreRelease());
// 1.2.3+build.42
Console.WriteLine(version.WithoutBuildMetadata());
// 1.2.3-rc.1Convert a semantic version back to its canonical string representation using ToString():
var version = new SemanticVersion(1, 2, 3, "rc.1", "build.42");
Console.WriteLine(version);
// 1.2.3-rc.1+build.42SemanticVersion implements IComparable<SemanticVersion>, IEquatable<SemanticVersion>, IParsable<SemanticVersion>, and ISpanParsable<SemanticVersion>.
It also supports the standard comparison and equality operators.
There is an important distinction between precedence and equality:
-
CompareTo,<,<=,>, and>=compare SemVer precedence and ignore build metadata. -
Equals,==, and!=compare all version components, including build metadata. -
HasSamePrecedence()explicitly tests whether two versions have the same SemVer precedence.
Two versions are equal when all their components are equal:
var v1 = SemanticVersion.Parse("1.2.3");
var v2 = SemanticVersion.Parse("1.2.3");
Console.WriteLine(v1 == v2);
// TrueBuild metadata is part of equality:
var v1 = SemanticVersion.Parse("1.2.3+build.1");
var v2 = SemanticVersion.Parse("1.2.3+build.2");
Console.WriteLine(v1 == v2);
// FalseOrdering follows the Semantic Versioning precedence rules:
var v1 = SemanticVersion.Parse("1.2.3");
var v2 = SemanticVersion.Parse("2.0.0");
Console.WriteLine(v1 < v2); // True
Console.WriteLine(v1 <= v2); // True
Console.WriteLine(v2 > v1); // True
Console.WriteLine(v2 >= v1); // TrueUse HasSamePrecedence() when build metadata should be ignored:
var v1 = SemanticVersion.Parse("1.0.0+build.1");
var v2 = SemanticVersion.Parse("1.0.0+build.2");
Console.WriteLine(v1.HasSamePrecedence(v2));
// TrueThe same result can be obtained through CompareTo():
Console.WriteLine(v1.CompareTo(v2));
// 0Prerelease versions always have lower precedence than the corresponding release version:
var prerelease = SemanticVersion.Parse("1.0.0-rc.1");
var release = SemanticVersion.Parse("1.0.0");
Console.WriteLine(prerelease < release);
// TrueThe implementation follows the precedence rules defined by the Semantic Versioning specification:
1.0.0-alpha
1.0.0-alpha.1
1.0.0-alpha.beta
1.0.0-beta
1.0.0-beta.2
1.0.0-beta.11
1.0.0-rc.1
1.0.0
Numeric prerelease identifiers are compared numerically, even when they exceed the range of a 32-bit integer.
Numeric identifiers always have lower precedence than non-numeric identifiers.
Build metadata is specified after a plus sign (+):
1.0.0+build.1
1.0.0-alpha+build.42
1.0.0-rc.1+20250810
Build metadata is preserved during parsing and formatting:
var version = SemanticVersion.Parse("1.0.0+build.42");
Console.WriteLine(version.BuildMetadata);
// build.42
Console.WriteLine(version.HasBuildMetadata);
// TrueAccording to the Semantic Versioning specification, build metadata does not affect version precedence:
var v1 = SemanticVersion.Parse("1.0.0+build.1");
var v2 = SemanticVersion.Parse("1.0.0+build.2");
Console.WriteLine(v1.CompareTo(v2)); // 0
Console.WriteLine(v1.HasSamePrecedence(v2)); // True
Console.WriteLine(v1 <= v2); // True
Console.WriteLine(v1 >= v2); // TrueHowever, SemanticVersion preserves build metadata as part of its value, so versions with different build metadata are not equal:
Console.WriteLine(v1 == v2); // False
Console.WriteLine(v1 != v2); // True