Bandingkan nomor versi tanpa menggunakan fungsi split

124

Bagaimana cara membandingkan nomor versi?

Misalnya:

x = 1.23.56.1487.5

y = 1.24.55.487.2

Sankar M
sumber
4
Apa yang Anda inginkan hasilnya?
BoltClock
4
versi dengan 5 bagian? Jika Anda menggunakan versi 4 bagian yang khas, Anda bisa menggunakan kelas System.Version, yang mencakup metode untuk membandingkan versi dan mengurai string versi
psousa
1
Apa jenis x dan y?
Gleno
5
Setiap kali seseorang berkata "Jangan gunakan X, Yatau Z", itu selalu membuat saya bertanya-tanya mengapa. Mengapa Anda tidak ingin menggunakan splitfungsi ini? The splitFungsi tampaknya seperti cara yang baik untuk melakukan hal ini jika Anda tidak akan menggunakan System.Versionkelas.
Bob2Chiv

Jawaban:

294

Bisakah Anda menggunakan kelas Versi?

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

Ini memiliki antarmuka IComparable. Ketahuilah bahwa ini tidak akan berfungsi dengan string versi 5-bagian seperti yang Anda tunjukkan (apakah itu benar-benar string versi Anda?). Dengan asumsi input Anda adalah string, inilah sampel yang berfungsi dengan string versi .NET 4-bagian normal:

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
sumber
5
Hanya jika versi terdiri dari 2-4 bagian
nama pengguna
@dev_Boston hanya satu pengecualian ... lakukan saja dengan nilai-nilai ini v1 = 1.0001 dan v2 = 1.1. itu memberi saya sama.
Sankar M
8
Ya, string versi bukan string desimal, dan menambahkan nol ke bagian nomor versi tidak relevan. Dengan kata lain, "00001" sama dengan "1" di bagian ke-2 dari string versi.
JohnD
8
Anda dapat membandingkan lebih mudah dibaca Version.Parse(v1) < Version.Parse(v2), karena operator >(Version v1, Version v2)diterapkan.
Andrey Moiseev
Ketahuilah bahwa Version.Parse ("6.0.0") kurang dari (<) Version.Parse ("6.0.0.0") (yaitu TIDAK sama). Debug.Assert(new Version("6.0.0") < new Version("6.0.0.0"));
adospace
13

Jika Anda dapat hidup dengan skema major.minor.build.revision Anda bisa menggunakan kelas Versi .Net . Kalau tidak, Anda harus menerapkan semacam parsing dari kiri ke kanan dan melanjutkan sampai Anda memiliki perbedaan atau kembali bahwa dua versi sama.

Andreas
sumber
7

Selain jawaban @JohnD mungkin ada kebutuhan untuk membandingkan hanya nomor versi parsial tanpa menggunakan Split ('.') Atau string lain <-> gembung konversi int. Saya baru saja menulis metode ekstensi CompareTo dengan 1 argumen tambahan - jumlah bagian signifikan dari nomor versi untuk membandingkan (antara 1 dan 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; 
    }
}
terlalu
sumber
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;
    }
pengguna3790307
sumber
14
Berhati-hatilah karena ini akan mengembalikan nilai yang sama untukcompareVersion("1.3", "1.3.1")
Ozgur Ozcitak
1

Jika karena alasan tertentu Anda tidak diizinkan untuk menggunakan metode perbandingan Versi secara langsung (misalnya dalam skenario client-server), pendekatan lain adalah mengekstraksi angka panjang dari versi dan kemudian membandingkan angka satu sama lain. Namun, nomor tersebut harus memiliki format berikut: Dua digit untuk Major, Minor dan Revisi dan empat digit untuk Build.

Cara mengekstrak nomor versi:

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

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

Dan kemudian di tempat lain Anda bisa membandingkan:

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

Catatan: versi terinstal adalah nomor lama yang sebelumnya diekstraksi

Fabian Bigler
sumber
Untuk memberikan semua angka 3 tempat, kodenya harus benar-benar: "version.Major * 1000000000L + version.Minor * 1000000L + version.Build * 1000L + version.Revision"
Stef Heyenrath
1
@StefHeyenrath Itu benar, jangan ragu untuk menyesuaikan kode di atas dengan kebutuhan Anda sendiri.
Fabian Bigler