Comparer les numéros de version sans utiliser la fonction de fractionnement

124

Comment comparer les numéros de version?

Par exemple:

x = 1,23,56,1487,5

y = 1,24,55,487,2

Sankar M
la source
4
Que voulez-vous que le résultat soit?
BoltClock
4
une version en 5 parties? Si vous utilisiez la version typique en 4 parties, vous pouvez utiliser la classe System.Version, qui comprend des méthodes pour comparer les versions et analyser la chaîne de version
psousa
1
Quels sont les types de x et y?
Gleno le
5
Chaque fois que quelqu'un dit : « Ne pas utiliser X, You Z», il me fait toujours me demande pourquoi. Pourquoi ne souhaitez-vous pas utiliser la splitfonction? La splitfonction semble être un bon moyen de le faire si vous n'allez pas utiliser la System.Versionclasse.
Bob2Chiv

Réponses:

294

Pouvez-vous utiliser la classe Version?

http://msdn.microsoft.com/en-us/library/system.version.aspx

Il a une interface IComparable. Sachez que cela ne fonctionnera pas avec une chaîne de version en 5 parties comme vous l'avez montré (est-ce vraiment votre chaîne de version?). En supposant que vos entrées sont des chaînes, voici un exemple de travail avec la chaîne de version en 4 parties .NET normale:

static class Program
{
    static void Main()
    {
        string v1 = "1.23.56.1487";
        string v2 = "1.24.55.487";

        var version1 = new Version(v1);
        var version2 = new Version(v2);

        var result = version1.CompareTo(version2);
        if (result > 0)
            Console.WriteLine("version1 is greater");
        else if (result < 0)
            Console.WriteLine("version2 is greater");
        else
            Console.WriteLine("versions are equal");
        return;

    }
}
JohnD
la source
5
Uniquement si la version se compose de 2-4 parties
nom d'utilisateur
@dev_Boston une seule exception ... il suffit de faire avec ces valeurs v1 = 1.0001 et v2 = 1.1. cela me donne égal.
Sankar M du
8
Oui, les chaînes de version ne sont pas des chaînes décimales et l'ajout de zéros à une partie du numéro de version n'est pas pertinent. En d'autres termes, "00001" est égal à "1" dans la 2ème partie de la chaîne de version.
JohnD du
8
Vous pouvez comparer plus lisiblement que Version.Parse(v1) < Version.Parse(v2), car operator >(Version v1, Version v2)est implémenté.
Andrey Moiseev
Sachez que Version.Parse ("6.0.0") est inférieur à (<) Version.Parse ("6.0.0.0") (c'est-à-dire ne sont PAS égaux). Debug.Assert(new Version("6.0.0") < new Version("6.0.0.0"));
adospace
13

Si vous pouvez vivre avec le schéma major.minor.build.revision, vous pouvez utiliser la classe .Net Version . Sinon, vous devrez implémenter une sorte d'analyse de gauche à droite et continuer jusqu'à ce que vous ayez une différence ou renvoyer que deux versions sont égales.

Andreas
la source
7

En plus de la réponse de @JohnD, il peut être nécessaire de ne comparer que des numéros de version partiels sans utiliser Split ('.') Ou une autre chaîne de conversion <-> int. Je viens d'écrire une méthode d'extension CompareTo avec 1 argument supplémentaire - nombre de parties significatives du numéro de version à comparer (entre 1 et 4).

public static class VersionExtensions
{
    public static int CompareTo(this Version version, Version otherVersion, int significantParts)
    {
        if(version == null)
        {
            throw new ArgumentNullException("version");
        }
        if(otherVersion == null)
        {
            return 1;
        }

        if(version.Major != otherVersion.Major && significantParts >= 1)
            if(version.Major > otherVersion.Major)
                return 1;
            else
                return -1;

        if(version.Minor != otherVersion.Minor && significantParts >= 2)
            if(version.Minor > otherVersion.Minor)
                return 1;
            else
                return -1;

        if(version.Build != otherVersion.Build && significantParts >= 3)
            if(version.Build > otherVersion.Build)
                return 1;
            else
                return -1;

        if(version.Revision != otherVersion.Revision && significantParts >= 4)
            if(version.Revision > otherVersion.Revision)
                return 1;
            else
                return -1;

        return 0; 
    }
}
aussi
la source
4
public int compareVersion(string Version1,string Version2)
    {
        System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"([\d]+)");
        System.Text.RegularExpressions.MatchCollection m1 = regex.Matches(Version1);
        System.Text.RegularExpressions.MatchCollection m2 = regex.Matches(Version2);
        int min = Math.Min(m1.Count,m2.Count);
        for(int i=0; i<min;i++)
        {
            if(Convert.ToInt32(m1[i].Value)>Convert.ToInt32(m2[i].Value))
            {
                return 1;
            }
            if(Convert.ToInt32(m1[i].Value)<Convert.ToInt32(m2[i].Value))
            {
                return -1;
            }               
        }
        return 0;
    }
user3790307
la source
14
Méfiez-vous que cela rendrait égal pourcompareVersion("1.3", "1.3.1")
Ozgur Ozcitak
1

Si, pour une raison quelconque, vous n'êtes pas autorisé à utiliser directement la méthode de comparaison de la version (par exemple dans un scénario client-serveur), une autre approche consiste à extraire un nombre long de la version, puis à comparer les nombres entre eux. Cependant, le numéro doit avoir le format suivant: deux chiffres pour Major, Minor et Revision et quatre pour Build.

Comment extraire le numéro de version:

var version = Assembly.GetExecutingAssembly().GetName().Version;

long newVersion = version.Major * 1000000000L + 
                   version.Minor * 1000000L + 
                   version.Build * 1000L + 
                   version.Revision;

Et puis ailleurs, vous pouvez simplement comparer:

if(newVersion > installedVersion)
{
  //update code
}

Remarque: InstallVersion est un nombre long précédemment extrait

Fabian Bigler
la source
Pour donner à tous les chiffres 3 places, le code doit en fait être: "version.Major * 1000000000L + version.Minor * 1000000L + version.Build * 1000L + version.Revision"
Stef Heyenrath
1
@StefHeyenrath C'est correct, n'hésitez pas à adapter le code ci-dessus à vos propres besoins.
Fabian Bigler