เปรียบเทียบหมายเลขเวอร์ชันโดยไม่ใช้ฟังก์ชันแยก


124

ฉันจะเปรียบเทียบหมายเลขเวอร์ชันได้อย่างไร

ตัวอย่างเช่น:

x = 1.23.56.1487.5

y = 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 ส่วนอย่างที่คุณแสดง (นั่นคือสตริงเวอร์ชันของคุณจริงหรือ) สมมติว่าอินพุตของคุณเป็นสตริงนี่คือตัวอย่างที่ใช้งานได้กับสตริงเวอร์ชัน 4. 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;

    }
}

5
เฉพาะในกรณีที่เวอร์ชันประกอบด้วย 2-4 ส่วน
ชื่อผู้ใช้

@dev_Boston มีข้อยกเว้นเพียงข้อเดียว ... แค่ทำกับค่าเหล่านี้ v1 = 1.0001 และ v2 = 1.1 มันให้ฉันเท่ากัน
Sankar M

8
ใช่สตริงเวอร์ชันไม่ใช่สตริงทศนิยมและการกำหนดค่าศูนย์ล่วงหน้าไปยังส่วนหนึ่งของหมายเลขเวอร์ชันไม่เกี่ยวข้อง กล่าวอีกนัยหนึ่ง "00001" เท่ากับ "1" ในส่วนที่ 2 ของสตริงเวอร์ชัน
JohnD

8
คุณสามารถเปรียบเทียบได้ง่ายขึ้นVersion.Parse(v1) < Version.Parse(v2)เนื่องจากoperator >(Version v1, Version v2)มีการใช้งาน
Andrey Moiseev

โปรดทราบว่า 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 มิฉะนั้นคุณจะต้องใช้การแยกวิเคราะห์บางประเภทจากซ้ายไปขวาและดำเนินการต่อไปจนกว่าคุณจะได้ผลต่างหรือส่งคืนว่าสองเวอร์ชันเท่ากัน


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;
    }

14
ระวังว่าสิ่งนี้จะกลับมาเท่ากับcompareVersion("1.3", "1.3.1")
Ozgur Ozcitak

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
}

หมายเหตุ: installedVersion เป็นตัวเลขแบบยาวที่แยกไว้ก่อนหน้านี้


หากต้องการให้ตัวเลขทั้งหมดเป็น 3 ตำแหน่งรหัสควรเป็น: "version.Major * 1000000000L + version.Minor * 1000000L + version.Build * 1000L + version.Revision"
Stef Heyenrath

1
@StefHeyenrath ถูกต้องอย่าลังเลที่จะปรับรหัสด้านบนตามความต้องการของคุณเอง
Fabian Bigler
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.