5

How can you compare two version numbers?

I don't want the simple 1.0.0.0 but I'm looking for comparing these

1.0.0.1

1.0.0.1rc1 / 1.0.0.1-rc1

1.0.0.1b

1.0.0.1a / 1.0.0.1-a

and so on

They are ordered in the direction of what is newest.

Quote from PHP.net from their function that does what I want

version_compare() compares two "PHP-standardized" version number strings. The function first replaces _, - and + with a dot . in the version strings and also inserts dots . before and after any non number so that for example '4.3.2RC1' becomes '4.3.2.RC.1'. Then it compares the parts starting from left to right. If a part contains special version strings these are handled in the following order: any string not found in this list < dev < alpha = a < beta = b < RC = rc < # < pl = p. This way not only versions with different levels like '4.1' and '4.1.2' can be compared but also any PHP specific version containing development state.

How can this be done?

Or is there something like this by default?

Bill Tarbell
  • 4,933
  • 2
  • 32
  • 52
joveice
  • 113
  • 2
  • 11
  • As far as I know, there is no built in functionality to do these sort of things in C#. Does your use case allow you to represent the version as custom type? – Rickless Mar 17 '18 at 15:06
  • 2
    The `Version` type could be of use but you’d still have to handle the suffix on your own: https://stackoverflow.com/questions/7568147/compare-version-numbers-without-using-split-function – blins Mar 17 '18 at 15:08
  • @Mahmoud what do you mean by "custom type"? – joveice Mar 17 '18 at 15:10
  • See @blins comment, if the built in `Version` type doesn't fit your needs. I mean, creating a custom class `Version` to represent the version. But first, take a look at this built in class, I didn't know it exists in `.Net` – Rickless Mar 17 '18 at 15:12
  • @Mahmoud that doesn't work with letters. I set my version with public string version = "version goes here" – joveice Mar 17 '18 at 15:16
  • You mean, you can't use any type other than `String` to represent the version? If that's the case, you can create an extension function for `String` to compare versions. I'd rather go with the `Version` class. – Rickless Mar 17 '18 at 15:19
  • @Mahmoud as I said, it does NOT support letters. – joveice Mar 17 '18 at 15:21
  • 1
    Use standard version semantic https://semver.org – M.Hassan Mar 17 '18 at 16:04
  • Why do you need to compare the versions? Typically, in .NET we use the `AssemblyVersionAttribute` to version the assembly and the `Version` class for comparing assembly versions. To support semver, you can use the `AssemblyInformationalVersionAttribute`, which allows *any string* in the field. Deployment comparisons often use NuGet which now fully supports semver in its version numbers, but the actual assemblies it deploys do not support semver (only as an informational version which has no comparison mechanism). – NightOwl888 Mar 17 '18 at 16:51
  • @M.Hassan that won't change a thing, the default version class does not support it. – joveice Mar 17 '18 at 17:12
  • My comment is advice, but sure not solving your problem. Github, nuget and others use this standard, so it's easy to compare versions. – M.Hassan Mar 17 '18 at 17:16
  • @NightOwl888 Because I'm checking if there is an update on different things, and that's why I need to be able to check these versions. M.Hassan same for you, I need to check if there are updates on these, and to do so I need to check these types of versions since there are plenty of ways to write version numbers there needs to be plenty of ways to check for them too :P – joveice Mar 17 '18 at 17:25
  • @joveice, as you say "there are plenty of ways to write version numbers",So what is the naming convention for your version. AFAIK, PHP-standardized number format is semantic versioning, https://stackoverflow.com/questions/35843943/what-is-php-standardized-version-number-strings also for php see: https://github.com/composer/semver – M.Hassan Mar 17 '18 at 17:43
  • @M.Hassan Didn't notice that, well then I'm following the standardized number format, and I need a way to check for it in c#. – joveice Mar 17 '18 at 17:58

3 Answers3

11

Use the semantic version library for .Net

To install the package:

 Install-Package semver

You can parse /compare versions.

Example 1: Compare

     var v1 = new SemVersion(1, 0, 0, "rc1");
     Console.WriteLine(v1);
     var v2 = new SemVersion(1, 0, 0, "rc2");
     Console.WriteLine(v2);
     var r = SemVersion.Compare(v1,v2);
     //If v1 < v2   return -1
     //if v1 > v2   return +1
     //if v1 = v2   return 0
     Console.WriteLine(r); // -1

Example2: Parse

     var version = SemVersion.Parse("1.2.45-alpha-beta+nightly.23.43-bla");
    Console.WriteLine(version);
    Console.WriteLine( version.Major); //1
    Console.WriteLine( version.Minor); //2
    Console.WriteLine( version.Patch); //45
    Console.WriteLine(version.Prerelease); //alpha-beta
    Console.WriteLine(version.Build); //nightly.23.43

Update:

Life demo in fiddle

M.Hassan
  • 10,282
  • 5
  • 65
  • 84
0

Rather than using a 3rd party's library it would be preferable to just reference Nuget.Core and utilize their SemanticVersion class. This class works very similarly to the standard Version object in .net but adheres to the Semantic Versioning spec (https://semver.org). It will parse your string into an IComparable and IEquatable object so you can compare multiple versions or sort them within a collection, etc.

Nuget.Core: https://www.nuget.org/packages/nuget.core/ (you can pull this library via nuget)

https://github.com/NuGet/NuGet2/blob/2.13/src/Core/SemanticVersion.cs

var rawVersions = new [] {"v1.4.0", "v1.4.0-patch10", "v1.4.0-patch2"};
var versions = rawVersions.Select(v => new SemanticVersion(v));
var sorted = versions.ToList().Sort();
Bill Tarbell
  • 4,933
  • 2
  • 32
  • 52
0

My function to comparison two versions. Version example "1.22.333.4444"

static int CompareVersions(string First, string Second)
{
    var IntVersions = new List<int[]>
    {
        Array.ConvertAll(First.Split('.'), int.Parse),
        Array.ConvertAll(Second.Split('.'), int.Parse)
    };
    var Cmp = IntVersions.First().Length.CompareTo(IntVersions.Last().Length);
    if (Cmp == 0)
        IntVersions = IntVersions.Select(v => { Array.Resize(ref v, IntVersions.Min(x => x.Length)); return v; }).ToList();
    var StrVersions = IntVersions.ConvertAll(v => string.Join("", Array.ConvertAll(v,
                        i => { return i.ToString($"D{IntVersions.Max(x => x.Max().ToString().Length)}"); })));
    var CmpVersions = StrVersions.OrderByDescending(i => i).ToList();
    return CmpVersions.First().Equals(CmpVersions.Last()) ? Cmp : CmpVersions.First().Equals(StrVersions.First()) ? 1 : -1;
}
First > Second 1
First == Second 0
First < Second -1
CTAJIUH
  • 1
  • 2