Skip to content

Proposal: Adding System.SemanticVersion #19317

@NickCraver

Description

@NickCraver

AB#1115515
One of the issues I keep running into with the "default open" world: prereleases. As more and more projects move to semantic versioning, it'd be nice to have a built-in type to handle these. Today, this fails:

Version.Parse("1.0.0-beta1");

Because System.Version has no concept of pre-release suffixes. I'm not arguing it should be added (that's maybe a little to breaking).

Instead how about a new type? System.SemanticVersion The main property most people would be interested in is the prerelease label, but other tenants of semantic versioning should be included. Comparisons being a big one. A lot of devs get this wrong on corner cases. I was looking for how to do best structure this and noticed: NuGet is already doing it. Here's their SemanticVersion class: (part 1, part2).

The API likely needs a little refinement for general use in the BCL, but is there a desire for this from others? I have use cases from parsing package versions to determining which version of Elasticsearch a client is connected to. There's a broad spectrum of semantic versioning use cases now.

Suggestions from others (collating here):

  • It should be comparable to Version (additional operator overloads)

API

namespace System 
{
    public class SemanticVersion : IFormattable, IComparable, IComparable<SemanticVersion>, IEquatable<SemanticVersion>, ICloneable
    {
        public SemanticVersion(int major, int minor, int patch);
        public SemanticVersion(int major, int minor, int patch, string prereleaseLabel);
        public SemanticVersion(int major, int minor, int patch, string prereleaseLabel, string metadata);
        public SemanticVersion(int major, int minor, int patch, IEnumerable<string> prereleaseLabel, IEnumerable<string> metadata);
        public SemanticVersion(string version);

        protected SemanticVersion(Version version, string prereleaseLabel = null, string metadata = null);
        protected SemanticVersion(Version version, IEnumerable<string> prereleaseLabels, IEnumerable<string> metadata);

        public int Major { get; }
        public int Minor { get; }
        public int Patch { get; }
        public virtual IEnumerable<string> PrereleaseLabels { get; }
        public virtual bool IsPrerelease { get; }
        public virtual IEnumerable<string> Metadata { get; }
        public virtual bool HasMetadata { get; }

        public virtual string ToString(string format, IFormatProvider formatProvider);

        public override string ToString();
        public override int GetHashCode();

        public virtual SemanticVersion Clone();
        object ICloneable.Clone() => Clone();

        public virtual bool Equals(SemanticVersion other);
        public virtual bool Equals(Version other);

        public virtual int CompareTo(object obj);
        public virtual int CompareTo(SemanticVersion other);
        public virtual int CompareTo(Version other);

        public static SemanticVersion Parse(string versionString);
        public static bool TryParse(string versionString, out SemanticVersion version);

        public static bool operator ==(SemanticVersion left, SemanticVersion right);
        public static bool operator !=(SemanticVersion left, SemanticVersion right);
        public static bool operator <(SemanticVersion left, SemanticVersion right);
        public static bool operator <=(SemanticVersion left, SemanticVersion right);
        public static bool operator >(SemanticVersion left, SemanticVersion right);
        public static bool operator >=(SemanticVersion left, SemanticVersion right);
 
        public static bool operator ==(Version left, SemanticVersion right);
        public static bool operator !=(Version left, SemanticVersion right);
        public static bool operator <(Version left, SemanticVersion right);
        public static bool operator <=(Version left, SemanticVersion right);
        public static bool operator >(Version left, SemanticVersion right);
        public static bool operator >=(Version left, SemanticVersion right);

        public static explicit operator SemanticVersion(Version version); 

        public static bool operator ==(SemanticVersion left, Version right);
        public static bool operator !=(SemanticVersion left, Version right);
        public static bool operator <(SemanticVersion left, Version right);
        public static bool operator <=(SemanticVersion left, Version right);
        public static bool operator >(SemanticVersion left, Version right);
        public static bool operator >=(SemanticVersion left, Version right);
    }
}

Metadata

Metadata

Assignees

Labels

api-needs-workAPI needs work before it is approved, it is NOT ready for implementationarea-System.Runtimedesign-discussionOngoing discussion about design without consensus

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions