不使用split函数比较版本号
本文关键字:比较 版本号 函数 split | 更新日期: 2023-09-27 18:09:54
如何比较版本号?
例如:x = 1.23.56.1487.5
y = 1.24.55.487.2
可以使用Version
类吗?
https://learn.microsoft.com/en-us/dotnet/api/system.version
它有一个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;
}
}
如果你能接受major.minor.build.revision方案,你可以使用。net Version类。否则,您必须实现某种从左到右的解析,并继续进行,直到有差异或返回两个版本相等。
除了@JohnD的答案之外,可能还需要只比较部分版本号,而不需要使用Split('.')或其他字符串<-> int转换。我刚刚写了一个扩展方法CompareTo与一个额外的参数-版本号的重要部分的数量进行比较(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;
}
}
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;
}
这是我的。我需要比较一些古怪的版本字符串,比如"3.2.1.7650.b40"与"3.10.1"所以我不能像上面建议的那样使用VersionInfo对象。这是又快又脏的,所以请告诉我风格。我还提供了一个简短的函数来测试它。
using System;
public class Program
{
public static void Main()
{
Test_CompareVersionStrings();
}
/// <summary>
/// Compare two version strings, e.g. "3.2.1.0.b40" and "3.10.1.a".
/// V1 and V2 can have different number of components.
/// Components must be delimited by dot.
/// </summary>
/// <remarks>
/// This doesn't do any null/empty checks so please don't pass dumb parameters
/// </remarks>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <returns>
/// -1 if v1 is lower version number than v2,
/// 0 if v1 == v2,
/// 1 if v1 is higher version number than v2,
/// -1000 if we couldn't figure it out (something went wrong)
/// </returns>
private static int CompareVersionStrings(string v1, string v2)
{
int rc = -1000;
v1 = v1.ToLower();
v2 = v2.ToLower();
if (v1 == v2)
return 0;
string[] v1parts = v1.Split('.');
string[] v2parts = v2.Split('.');
for (int i = 0; i < v1parts.Length; i++)
{
if (v2parts.Length < i+1)
break; // we're done here
string v1Token = v1parts[i];
string v2Token = v2parts[i];
int x;
bool v1Numeric = int.TryParse(v1Token, out x);
bool v2Numeric = int.TryParse(v2Token, out x);
// handle scenario {"2" versus "20"} by prepending zeroes, e.g. it would become {"02" versus "20"}
if (v1Numeric && v2Numeric) {
while (v1Token.Length < v2Token.Length)
v1Token = "0" + v1Token;
while (v2Token.Length < v1Token.Length)
v2Token = "0" + v2Token;
}
rc = String.Compare(v1Token, v2Token, StringComparison.Ordinal);
//Console.WriteLine("v1Token=" + v1Token + " v2Token=" + v2Token + " rc=" + rc);
if (rc != 0)
break;
}
if (rc == 0)
{
// catch this scenario: v1="1.0.1" v2="1.0"
if (v1parts.Length > v2parts.Length)
rc = 1; // v1 is higher version than v2
// catch this scenario: v1="1.0" v2="1.0.1"
else if (v2parts.Length > v1parts.Length)
rc = -1; // v1 is lower version than v2
}
if (rc == 0 || rc == -1000)
return rc;
else
return rc < 0 ? -1 : 1;
}
private static int _CompareVersionStrings(string v1, string v2)
{
int rc = CompareVersionStrings(v1, v2);
Console.WriteLine("Compare v1: " + v1 + " v2: " + v2 + " result: " + rc);
return rc;
}
// for debugging
private static void Test_CompareVersionStrings()
{
bool allPass = true;
// should be equal
allPass &= (0 == _CompareVersionStrings("1", "1"));
allPass &= (0 == _CompareVersionStrings("1.1", "1.1"));
allPass &= (0 == _CompareVersionStrings("3.3.a20", "3.3.A20"));
// v1 should be lower
allPass &= (-1 == _CompareVersionStrings("1", "2"));
allPass &= (-1 == _CompareVersionStrings("1.0", "1.0.1"));
allPass &= (-1 == _CompareVersionStrings("1.0", "1.1"));
allPass &= (-1 == _CompareVersionStrings("1.0.0.3", "1.1"));
allPass &= (-1 == _CompareVersionStrings("1.2.3.4", "1.2.3.4b"));
allPass &= (-1 == _CompareVersionStrings("1.2.3.4", "1.2.3.4.b"));
allPass &= (-1 == _CompareVersionStrings("1.8.0", "20.0.0.0"));
allPass &= (-1 == _CompareVersionStrings("5.6.0.788.2", "20.0.0.0"));
// v1 should be higher
allPass &= (1 == _CompareVersionStrings("2", "1"));
allPass &= (1 == _CompareVersionStrings("1.0.1", "1.0"));
allPass &= (1 == _CompareVersionStrings("1.1", "1.0"));
allPass &= (1 == _CompareVersionStrings("1.1", "1.0.0.3"));
allPass &= (1 == _CompareVersionStrings("1.2.3.4b", "1.2.3.4"));
allPass &= (1 == _CompareVersionStrings("1.2.3.4.b", "1.2.3.4"));
allPass &= (1 == _CompareVersionStrings("20.0.0.0", "5.6.0.788.2"));
Console.WriteLine("allPass = " + allPass.ToString());
}
}
如果由于某些原因不允许直接使用版本的比较方法(例如在客户机-服务器场景中),另一种方法是从版本中提取一个长数字,然后相互比较这些数字。但是,该数字需要具有以下格式: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是先前提取的长数字
我在网上发现这个算法似乎工作得很好。
//https://www.geeksforgeeks.org/compare-two-version-numbers/amp/
static int versionCompare(string v1, string v2)
{
// vnum stores each numeric
// part of version
int vnum1 = 0, vnum2 = 0;
// loop until both string are
// processed
for (int i = 0, j = 0; (i < v1.Length || j < v2.Length);)
{
// storing numeric part of
// version 1 in vnum1
while (i < v1.Length && v1[i] != '.')
{
vnum1 = vnum1 * 10 + (v1[i] - '0');
i++;
}
// storing numeric part of
// version 2 in vnum2
while (j < v2.Length && v2[j] != '.')
{
vnum2 = vnum2 * 10 + (v2[j] - '0');
j++;
}
if (vnum1 > vnum2)
return 1;
if (vnum2 > vnum1)
return -1;
// if equal, reset variables and
// go for next numeric part
vnum1 = vnum2 = 0;
i++;
j++;
}
return 0;
}