27 using System.Globalization;
28 using System.Runtime.Serialization;
29 using System.Security.Permissions;
31 using System.Text.RegularExpressions;
40 public sealed
class SemVersion : IComparable<SemVersion>, IComparable
43 internal sealed class
SemVersion : IComparable<SemVersion>, IComparable, ISerializable
46 static Regex parseEx =
47 new Regex(
@"^(?<major>\d+)" +
48 @"(\.(?<minor>\d+))?" +
49 @"(\.(?<patch>\d+))?" +
50 @"(\-(?<pre>[0-9A-Za-z\-\.]+))?" +
51 @"(\+(?<build>[0-9A-Za-z\-\.]+))?$",
53 RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture);
55 RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.ExplicitCapture);
59 private SemVersion(SerializationInfo info, StreamingContext context)
67 if (info ==
null)
throw new ArgumentNullException(
"info");
68 var semVersion =
Parse(info.GetString(
"SemVersion"));
69 Major = semVersion.Major;
70 Minor = semVersion.Minor;
71 Patch = semVersion.Patch;
73 Build = semVersion.Build;
85 public SemVersion(
int major,
int minor = 0,
int patch = 0,
string prerelease =
"",
string build =
"")
92 this.
Build = build ??
"";
103 throw new ArgumentNullException(
"version");
105 this.
Major = version.Major;
106 this.
Minor = version.Minor;
108 if (version.Revision >= 0)
110 this.
Patch = version.Revision;
115 if (version.Build > 0)
117 this.
Build = version.Build.ToString();
121 this.
Build = String.Empty;
134 var match = parseEx.Match(version);
141 var major =
int.Parse(match.Groups[
"major"].Value);
143 var major =
int.Parse(match.Groups[
"major"].Value, CultureInfo.InvariantCulture);
146 var minorMatch = match.Groups[
"minor"];
148 if (minorMatch.Success)
151 minor =
int.Parse(minorMatch.Value);
153 minor =
int.Parse(minorMatch.Value, CultureInfo.InvariantCulture);
158 throw new InvalidOperationException(
"Invalid version (no minor version given in strict mode)");
161 var patchMatch = match.Groups[
"patch"];
163 if (patchMatch.Success)
166 patch =
int.Parse(patchMatch.Value);
168 patch =
int.Parse(patchMatch.Value, CultureInfo.InvariantCulture);
173 throw new InvalidOperationException(
"Invalid version (no patch version given in strict mode)");
176 var prerelease = match.Groups[
"pre"].Value;
177 var build = match.Groups[
"build"].Value;
179 return new SemVersion(major, minor, patch, prerelease, build);
195 semver =
Parse(version, strict);
213 if (ReferenceEquals(versionA,
null))
214 return ReferenceEquals(versionB,
null);
215 return versionA.
Equals(versionB);
227 if (ReferenceEquals(versionA,
null))
228 return ReferenceEquals(versionB,
null) ? 0 : -1;
242 string prerelease =
null,
string build =
null)
249 build ?? this.
Build);
258 public int Major {
get;
private set; }
266 public int Minor {
get;
private set; }
274 public int Patch {
get;
private set; }
290 public string Build {
get;
private set; }
303 if (!String.IsNullOrEmpty(
Build))
304 version +=
"+" +
Build;
341 if (ReferenceEquals(other,
null))
348 r = CompareComponent(this.
Build, other.
Build);
375 if (ReferenceEquals(other,
null))
379 if (r != 0)
return r;
382 if (r != 0)
return r;
385 if (r != 0)
return r;
391 static int CompareComponent(
string a,
string b,
bool lower =
false)
393 var aEmpty = String.IsNullOrEmpty(a);
394 var bEmpty = String.IsNullOrEmpty(b);
395 if (aEmpty && bEmpty)
399 return lower ? 1 : -1;
401 return lower ? -1 : 1;
403 var aComps = a.Split(
'.');
404 var bComps = b.Split(
'.');
406 var minLen = Math.Min(aComps.Length, bComps.Length);
407 for (
int i = 0; i < minLen; i++)
412 var isanum = Int32.TryParse(ac, out anum);
413 var isbnum = Int32.TryParse(bc, out bnum);
415 if (isanum && isbnum)
417 r = anum.CompareTo(bnum);
418 if (r != 0)
return anum.CompareTo(bnum);
426 r = String.CompareOrdinal(ac, bc);
432 return aComps.Length.CompareTo(bComps.Length);
444 if (ReferenceEquals(obj,
null))
447 if (ReferenceEquals(
this, obj))
452 return this.
Major == other.Major &&
453 this.
Minor == other.Minor &&
454 this.
Patch == other.Patch &&
455 string.Equals(this.
Prerelease, other.Prerelease, StringComparison.Ordinal) &&
456 string.Equals(this.
Build, other.Build, StringComparison.Ordinal);
469 int result = this.
Major.GetHashCode();
470 result = result * 31 + this.
Minor.GetHashCode();
471 result = result * 31 + this.
Patch.GetHashCode();
472 result = result * 31 + this.
Prerelease.GetHashCode();
473 result = result * 31 + this.
Build.GetHashCode();
479 [SecurityPermission(SecurityAction.Demand, SerializationFormatter =
true)]
480 public void GetObjectData(SerializationInfo info, StreamingContext context)
482 if (info ==
null)
throw new ArgumentNullException(
"info");
483 info.AddValue(
"SemVersion",
ToString());
538 return left == right || left > right;
560 return left == right || left < right;
static bool operator<=(SemVersion left, SemVersion right)
The override of the less than or equal operator.
int CompareTo(object obj)
Compares the current instance with another object of the same type and returns an integer that indica...
static int Compare(SemVersion versionA, SemVersion versionB)
Compares the specified versions.
A semantic version implementation. Conforms to v2.0.0 of http://semver.org/
SemVersion(int major, int minor=0, int patch=0, string prerelease="", string build="")
Initializes a new instance of the SemVersion class.
int Major
Gets the major version.
SemVersion Change(int? major=null, int? minor=null, int? patch=null, string prerelease=null, string build=null)
Make a copy of the current instance with optional altered fields.
override bool Equals(object obj)
Determines whether the specified System.Object is equal to this instance.
int CompareByPrecedence(SemVersion other)
Compares to semantic versions by precedence. This does the same as a Equals, but ignores the build in...
static SemVersion Parse(string version, bool strict=false)
Parses the specified string to a semantic version.
static bool operator<(SemVersion left, SemVersion right)
The override of the less operator.
string Build
Gets the build version.
static bool Equals(SemVersion versionA, SemVersion versionB)
Tests the specified versions for equality.
override string ToString()
Returns a System.String that represents this instance.
int CompareTo(SemVersion other)
Compares the current instance with another object of the same type and returns an integer that indica...
bool PrecedenceMatches(SemVersion other)
Compares to semantic versions by precedence. This does the same as a Equals, but ignores the build in...
int Patch
Gets the patch version.
static bool operator==(SemVersion left, SemVersion right)
The override of the equals operator.
override int GetHashCode()
Returns a hash code for this instance.
static bool TryParse(string version, out SemVersion semver, bool strict=false)
Parses the specified string to a semantic version.
string Prerelease
Gets the pre-release version.
static bool operator >=(SemVersion left, SemVersion right)
The override of the greater than or equal operator.
static bool operator >(SemVersion left, SemVersion right)
The override of the greater operator.
SemVersion(SerializationInfo info, StreamingContext context)
Initializes a new instance of the SemVersion class.
static bool operator !=(SemVersion left, SemVersion right)
The override of the un-equal operator.
int Minor
Gets the minor version.
SemVersion(Version version)
Initializes a new instance of the SemVersion class.