using Serilog; // Make a version since it is so much easier to compare when the class handles it. sealed class Version : IComparable, IEquatable { public int Major { get; private set; } public int Minor { get; private set; } public int Build { get; private set; } public int Patch { get; private set; } public int Subpatch { get; private set; } public Version(string versionString) { Log.Information("Creating version from string {versionString}", versionString); if (versionString == "") { throw new ArgumentException("The passed version string was empty", "versionString"); } var splitVersion = versionString.Split('.'); Log.Debug("SplitVersion = {@splitversion}", splitVersion); Major = int.Parse(splitVersion[0]); Minor = int.Parse(splitVersion[1]); Build = int.Parse(splitVersion[2]); var splitPatch = splitVersion[3].Split('-'); Log.Debug("SplitPatch = {@splitPatch}", splitPatch); Log.Debug("SplitPatch values : [0] = {0}, [1] = {1}", splitPatch[0], splitPatch[1]); Patch = int.Parse(splitPatch[0]); Subpatch = int.Parse(splitPatch[1]); Log.Debug("Version Created: {@version}", this); } public override string ToString() { return $"{Major}.{Minor}.{Build}.{Patch}-{Subpatch}"; } public int CompareTo(Version? other) { if (other is null) { return 1; } // full Equality is easy since everything should be the same. // OPTIM: Doing this here is techinally more effecient than baking it in to the later code // Bools and shit if (this.Major == other.Major && this.Minor == other.Minor && this.Build == other.Build && this.Patch == other.Patch && this.Subpatch == other.Subpatch) { return 0; } // Compare major version if (Major != other.Major) return Major.CompareTo(other.Major); // Compare minor version if (Minor != other.Minor) return Minor.CompareTo(other.Minor); // Compare build number if (Build != other.Build) return Build.CompareTo(other.Build); // Compare patch number if (Patch != other.Patch) return Patch.CompareTo(other.Patch); // Compare subpatch number return Subpatch.CompareTo(other.Subpatch); } public override bool Equals(object? obj) { if (obj is null || !this.GetType().Equals(obj.GetType())) { return false; } return this.Equals(obj); // NOTE: For the purposes of a version number same values == same version } public override int GetHashCode() { return Major + Minor + Build + Patch + Subpatch; // NOTE: For the purposes of a version number same values == same version // That is why this "hash" code will collide given two "different" versions with the same values } public bool Equals(Version? other) { if (other is null) { return false; } return this.CompareTo(other) == 0; } public static bool operator >(Version v1, Version v2) { return v1.CompareTo(v2) > 0; } public static bool operator <(Version v1, Version v2) { return v1.CompareTo(v2) < 0; } public static bool operator >=(Version v1, Version v2) { return v1.CompareTo(v2) >= 0; } public static bool operator <=(Version v1, Version v2) { return v1.CompareTo(v2) <= 0; } }