Parsing
Parsing turns a version string into a SemVer; use this page to choose between the throwing and non-throwing
overloads and to see exactly which strings are accepted. SemVer accepts version strings in the canonical
SemVer 2.0.0 format:
MAJOR.MINOR.PATCH[-PRERELEASE][+METADATA]
Where:
MAJOR,MINOR, andPATCHare non-negative integers with no leading zeros (except0itself).PRERELEASEis an optional dot-separated sequence of alphanumeric identifiers and hyphens.METADATAis an optional dot-separated sequence of alphanumeric identifiers and hyphens following+.
Parse — throwing overload
Use Parse when you expect the input to always be valid:
SemVer v = SemVer.Parse("1.2.3");
SemVer v = SemVer.Parse("1.2.3-alpha");
SemVer v = SemVer.Parse("1.2.3+build.456");
SemVer v = SemVer.Parse("1.2.3-alpha.1+build.456");
Throws ArgumentException for any string that does not match the SemVer 2.0.0 grammar,
ArgumentNullException for null, and OverflowException when MAJOR, MINOR or PATCH is larger than
int.MaxValue.
TryParse — non-throwing overload
Use TryParse when the input may be invalid (user input, config files, etc.):
if (SemVer.TryParse("1.0.0-rc.1", out var version))
{
// version is valid — use it
Console.WriteLine(version.PreRelease); // rc.1
}
else
{
// string was not a valid SemVer
}
Returns false and sets result to null when parsing fails (including null input and components larger
than int.MaxValue). Never throws. The IFormatProvider parameter of the ISpanParsable<SemVer> overloads is
ignored; parsing is culture-independent.
ISpanParsable<SemVer> — span overloads
All parsing methods also accept ReadOnlySpan<char>, so SemVer works with generic code constrained to
ISpanParsable<T>. The span is copied to a string before parsing:
ReadOnlySpan<char> span = "1.0.0-beta".AsSpan();
// Throwing
SemVer v = SemVer.Parse(span, null);
// Non-throwing
if (SemVer.TryParse(span, null, out var version))
{
// ...
}
// Convenience overload without IFormatProvider
if (SemVer.TryParse(span, out var version2))
{
// ...
}
Valid and invalid examples
| Input | Valid? | Notes |
|---|---|---|
1.0.0 |
✅ | Minimal release version |
0.0.0 |
✅ | Zero version |
10.20.30 |
✅ | Large version numbers |
1.0.0-alpha |
✅ | Pre-release |
1.0.0+build |
✅ | Build metadata only |
1.0.0-alpha+build |
✅ | Pre-release + metadata |
1.0.0-alpha.1+exp.sha.5114f85 |
✅ | Complex pre-release and metadata |
1.0 |
❌ | Missing patch component |
1.0.0.0 |
❌ | Four components (not SemVer) |
1..0 |
❌ | Empty component |
1.0.0- |
❌ | Empty pre-release |
1.0.0+ |
❌ | Empty metadata |
-1.0.0 |
❌ | Negative major |
a.0.0 |
❌ | Non-numeric major |
Implicit parse via string assignment
Because SemVer defines an implicit conversion from string, you can also write:
SemVer v = "1.0.0-rc.1"; // calls Parse internally
This uses the throwing Parse path, so an invalid string will throw ArgumentException.
See String Conversion for details.
What the parser validates
Under the hood, SemVer uses the official SemVer 2.0.0 regular expression:
^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)
(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?
(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
This ensures leading zeros are rejected (e.g. 01.0.0 is invalid) and all identifiers contain only the allowed character set.