Compare números de versão sem usar a função de divisão

124

Como eu comparo os números de versão?

Por exemplo:

x = 1.23.56.1487.5

y = 1.24.55.487.2

Sankar M
fonte
4
O que você quer que seja o resultado?
BoltClock
4
uma versão com 5 partes? Se você estiver usando a versão típica 4 parte você poderia usar a classe System.Version, que inclui métodos para comparar as versões e analisar a cadeia de versão
psousa
1
Quais são os tipos de xey?
Gleno
5
Sempre que alguém diz "Não use X, You Z", isso sempre me faz pensar o porquê. Por que você não deseja usar a splitfunção? A splitfunção parece ser uma boa maneira de fazer isso se você não for usar a System.Versionclasse.
Bob2Chiv

Respostas:

294

Você pode usar a classe Version?

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

Possui uma interface IComparable. Esteja ciente de que isso não funcionará com uma sequência de versões de 5 partes, como você mostrou (essa é realmente a sua sequência de versões?). Supondo que suas entradas sejam sequências de caracteres, aqui está um exemplo de trabalho com a sequência de versão normal em 4 partes do .NET:

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
fonte
5
Somente se a versão consistir em 2 a 4 partes
nome de usuário
@dev_Boston apenas uma exceção ... basta fazer com esses valores v1 = 1.0001 e v2 = 1.1. isso me dá igual.
Sankar M
8
Sim, as seqüências de caracteres de versão não são decimais, e a adição de zeros a uma parte do número da versão é irrelevante. Em outras palavras, "00001" é igual a "1" na segunda parte da cadeia de versão.
JohnD
8
Você pode comparar mais facilmente como Version.Parse(v1) < Version.Parse(v2), porque operator >(Version v1, Version v2)é implementado.
Andrey Moiseev
Esteja ciente de que Version.Parse ("6.0.0") é menor que (<) Version.Parse ("6.0.0.0") (ou seja, NÃO é igual). Debug.Assert(new Version("6.0.0") < new Version("6.0.0.0"));
adospace
13

Se você puder viver com o esquema major.minor.build.revision, poderá usar a classe .Net Version . Caso contrário, você teria que implementar algum tipo de análise da esquerda para a direita e continuar até ter uma diferença ou retornar que duas versões são iguais.

Andreas
fonte
7

Além da resposta de @JohnD, pode ser necessário comparar apenas números de versão parciais sem usar Split ('.') Ou outra string <-> int conversion bloat. Acabei de escrever um método de extensão CompareTo com 1 argumento adicional - número de partes significativas do número da versão a serem comparadas (entre 1 e 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; 
    }
}
também
fonte
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
fonte
14
Cuidado que isso retornaria igual para #compareVersion("1.3", "1.3.1")
Ozgur Ozcitak
1

Se, por algum motivo, você não tiver permissão para usar o método de comparação da versão diretamente (por exemplo, em um cenário cliente-servidor), outra abordagem é extrair um número longo da versão e depois comparar os números entre si. No entanto, o número precisa ter o seguinte formato: Dois dígitos para Maior, Menor e Revisão e quatro para Compilação.

Como extrair o número da versão:

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

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

E então, em outro lugar, você pode apenas comparar:

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

Nota: a versão instalada é um número longo extraído anteriormente

Fabian Bigler
fonte
Para atribuir a todos os dígitos três lugares, o código deve realmente ser: "version.Major * 1000000000L + version.Minor * 1000000L + version.Build * 1000L + version.Revision"
Stef Heyenrath
1
@StefHeyenrath Isso está correto, sinta-se à vontade para ajustar o código acima às suas próprias necessidades.
Fabian Bigler