patterncsharpMinor
Which version is the latest?
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
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
When you arrange the elements in ascending order, comparing
The above checks ensure that the Compare` function is well-behaved.
When building a utility class for this purpose, it could look like this:
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.
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 return0
- 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.