Сравните номера версий без использования функции разделения

124

Как сравнить номера версий?

Например:

х = 1,23,56,1487,5

у = 1,24,55,487,2

Санкар М
источник
4
Каким должен быть результат?
BoltClock
4
версия с 5 частями? Если вы использовали типичную версию из 4 частей, вы могли бы использовать класс System.Version, который включает методы для сравнения версий и анализа строки версии
psousa
1
Какие бывают типы x и y?
Gleno
5
Когда кто-то говорит: «Не используйте X, Yили Z», я всегда удивляюсь, почему. Почему вы не хотите использовать эту splitфункцию? splitФункция выглядит как хороший способ сделать это , если вы не собираетесь использовать System.Versionкласс.
Bob2Chiv

Ответы:

294

Можете ли вы использовать класс Version?

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

Имеет интерфейс IComparable. Имейте в виду, что это не будет работать со строкой версии из 5 частей, как вы показали (это действительно строка вашей версии?). Предполагая, что ваши входные данные являются строками, вот рабочий образец с обычной строкой версии .NET из 4 частей:

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
источник
5
Только если версия состоит из 2-4 частей
логин
@dev_Boston только одно исключение ... просто используйте эти значения v1 = 1.0001 и v2 = 1.1. это дает мне равные.
Sankar M
8
Да, строки версии не являются десятичными, и добавление нулей к части номера версии не имеет значения. Другими словами, «00001» равно «1» во второй части строки версии.
JohnD
8
Читательнее можно сравнить как Version.Parse(v1) < Version.Parse(v2), т.к. operator >(Version v1, Version v2)реализовано.
Андрей Моисеев
Имейте в виду, что Version.Parse ("6.0.0") меньше (<) Version.Parse ("6.0.0.0") (т. Е. НЕ равны). Debug.Assert(new Version("6.0.0") < new Version("6.0.0.0"));
adospace
13

Если вы можете жить со схемой major.minor.build.revision, вы можете использовать класс .Net Version . В противном случае вам придется реализовать какой-то синтаксический анализ слева направо и продолжать до тех пор, пока вы не получите разницу или не вернете, что две версии равны.

Andreas
источник
7

В дополнение к ответу @JohnD может возникнуть необходимость сравнить только частичные номера версий без использования Split ('.') Или другого раздувания преобразования строки <-> int. Я только что написал метод расширения CompareTo с 1 дополнительным аргументом - количеством значимых частей номера версии для сравнения (от 1 до 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; 
    }
}
слишком
источник
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
источник
14
Остерегайтесь, что это вернет равнозначноcompareVersion("1.3", "1.3.1")
Озгур Озчитак
1

Если по какой-то причине вам не разрешено использовать метод сравнения Версии напрямую (например, в сценарии клиент-сервер), другой подход состоит в том, чтобы извлечь длинное число из версии и затем сравнить числа друг с другом. Однако номер должен иметь следующий формат: две цифры для Major, Minor и Revision и четыре для Build.

Как извлечь номер версии:

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

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

А потом еще где-нибудь можно просто сравнить:

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

Примечание: установленная версия - это ранее извлеченное длинное число.

Фабиан Биглер
источник
Чтобы дать всем цифрам 3 разряда, код должен быть на самом деле: «version.Major * 1000000000L + version.Minor * 1000000L + version.Build * 1000L + version.Revision»
Stef Heyenrath
1
@StefHeyenrath Это правильно, не стесняйтесь изменять приведенный выше код в соответствии со своими потребностями.
Фабиан Биглер,