Compare los números de versión sin usar la función dividida

124

¿Cómo comparo los números de versión?

Por ejemplo:

x = 1.23.56.1487.5

y = 1.24.55.487.2

Sankar M
fuente
44
¿Cuál quieres que sea el resultado?
BoltClock
44
una versión con 5 partes? Si estaba usando la versión típica de 4 partes, podría usar la clase System.Version, que incluye métodos para comparar versiones y analizar la cadena de versión
psousa
1
¿Cuáles son los tipos de x e y?
Gleno
55
Cada vez que alguien dice "No usar X, Yo Z", siempre me hace preguntarme por qué. ¿Por qué no quieres usar la splitfunción? La splitfunción parece una buena manera de hacer esto si no vas a usar la System.Versionclase.
Bob2Chiv

Respuestas:

294

¿Puedes usar la clase Version?

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

Tiene una interfaz IComparable. Tenga en cuenta que esto no funcionará con una cadena de versión de 5 partes como la que ha mostrado (¿es realmente su cadena de versión?). Suponiendo que sus entradas son cadenas, aquí hay una muestra de trabajo con la cadena de versión normal .NET de 4 partes:

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
fuente
55
Solo si la versión consta de 2 a 4 partes
nombre de usuario del
@dev_Boston solo una excepción ... solo hazlo con estos valores v1 = 1.0001 y v2 = 1.1. me da igual.
Sankar M
8
Sí, las cadenas de versión no son cadenas decimales, y los ceros anteriores a una parte del número de versión son irrelevantes. En otras palabras, "00001" es igual a "1" en la segunda parte de la cadena de versión.
JohnD
8
Puede comparar más legible como Version.Parse(v1) < Version.Parse(v2), porque operator >(Version v1, Version v2)está implementado.
Andrey Moiseev
Tenga en cuenta que Version.Parse ("6.0.0") es menor que (<) Version.Parse ("6.0.0.0") (es decir, NO son iguales). Debug.Assert(new Version("6.0.0") < new Version("6.0.0.0"));
adospace
13

Si puede vivir con el esquema major.minor.build.revision, podría usar la clase .Net Version . De lo contrario, tendría que implementar algún tipo de análisis de izquierda a derecha y continuar hasta que tenga una diferencia o regrese que dos versiones son iguales.

Andreas
fuente
7

Además de la respuesta de @JohnD, podría ser necesario comparar solo números de versión parciales sin usar Split ('.') U otra cadena <-> int bloat de conversión. Acabo de escribir un método de extensión CompareTo con 1 argumento adicional: número de partes significativas del número de versión para comparar (entre 1 y 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; 
    }
}
también
fuente
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;
    }
usuario3790307
fuente
14
Tenga en cuenta que esto sería igual paracompareVersion("1.3", "1.3.1")
Ozgur Ozcitak
1

Si por alguna razón no se le permite usar el método de comparación de la Versión directamente (por ejemplo, en un escenario cliente-servidor), otro enfoque es extraer un número largo de la versión y luego comparar los números entre sí. Sin embargo, el número debe tener el siguiente formato: dos dígitos para mayor, menor y revisión y cuatro para compilación.

Cómo extraer el número de versión:

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

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

Y luego, en otro lugar, puedes comparar:

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

Nota: la versión instalada es un número largo previamente extraído

Fabian Bigler
fuente
Para dar a todos los dígitos 3 lugares, el código debería ser: "version.Major * 1000000000L + version.Minor * 1000000L + version.Build * 1000L + version.Revision"
Stef Heyenrath
1
@StefHeyenrath Eso es correcto, no dude en ajustar el código anterior a sus propias necesidades.
Fabian Bigler