HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Which version is the latest?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
whichversionthelatest

Problem

I have this little class for parsing, comparing and sorting semantic versions. I did my best to implement the specification at semver.org with one exception - it doesn't support the build metadata. Now you can tear it apart ;-)

I removed all parameter checks to make it shorter.

```
[DebuggerDisplay("{ToString(),nq}")]
public class SemanticVersion : IComparable, IComparer
{
private SemanticVersion() { }

public SemanticVersion(int major, int minor, int patch, IEnumerable labels = null)
{
Labels = labels?.ToList();
}

public static SemanticVersion Parse(string value)
{
var versionMatch = Regex.Match(value, @"v?(?\d+)\.(?\d+)\.(?\d+)(-(?.+))?", RegexOptions.IgnoreCase);
if (!versionMatch.Success)
{
return null;
}

return new SemanticVersion
{
Major = int.Parse(versionMatch.Groups["major"].Value),
Minor = int.Parse(versionMatch.Groups["minor"].Value),
Patch = int.Parse(versionMatch.Groups["patch"].Value),
Labels = versionMatch.Groups["labels"].Value.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries).ToList()
};
}

public int Major { get; private set; }

public int Minor { get; private set; }

public int Patch { get; private set; }

public List Labels { get; private set; }

public bool IsPrerelease => Labels?.Count > 0;

public override string ToString()
{
var versionNumber = $"{Major}.{Minor}.{Patch}";
if (Labels.Count > 0)
{
versionNumber = $"{versionNumber}-{string.Join(".", Labels)}";
}
return versionNumber;
}

public override int GetHashCode()
{
return ToString().GetHashCode();
}

public override bool Equals(object obj)
{
if (ReferenceEquals(obj, null))
{
return false;
}
var semVer = obj as SemanticVersion;
if (ReferenceEquals(semVer

Solution

Do not use Sort in unit tests, since that only tests very few cases. (Remember, sort algorithms are designed to use as few comparisons as possible.) Instead, make a list of elements you want to compare. Then, compare each element to each element, including itself.

When you arrange the elements in ascending order, comparing elements[i] with element[j] must have these results:

  • if i ≤ j, compare must return ≤ 0, in most cases



  • if i = j, compare must return 0



  • if i ≥ j, compare must return ≥ 0, in most cases > 0



The above checks ensure that the
Compare` function is well-behaved.

When building a utility class for this purpose, it could look like this:

ComparatorTester.For(comparator)
    .Next("0.0.0")
    .SameAsAbove("00.00.00", "0.000.000")
    .Next("0.0.1")
    .Next("1.0.0")
    .AssertAllOrdered();


This way, your unit test contains only a single but comprehensive list of version numbers and their intended relative order. Currently you have two separate lists.

Code Snippets

ComparatorTester.For(comparator)
    .Next("0.0.0")
    .SameAsAbove("00.00.00", "0.000.000")
    .Next("0.0.1")
    .Next("1.0.0")
    .AssertAllOrdered();

Context

StackExchange Code Review Q#145333, answer score: 2

Revisions (0)

No revisions yet.