不使用拆分函数比较版本号

如何比较版本号?

例如:

X = 1.23.56.1487.5

Y = 1.24.55.487.2

81926 次浏览

你能用 Version类吗?
Https://learn.microsoft.com/en-us/dotnet/api/system.version

它有一个 IComparable接口。请注意,这不适用于您所显示的由5个部分组成的版本字符串(这真的是您的版本字符串吗?).假设您的输入是字符串,这里有一个使用标准。NET 4-part 版本字符串:

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.Amendment 方案,那么您可以使用。净 版本级。否则,您将不得不实现某种从左到右的解析,并继续进行,直到出现差异或返回两个版本相等的结果。

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

除了@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;
}
}

如果由于某种原因您不能直接使用 Version 的比较方法(例如,在客户机-服务器场景中) ,另一种方法是从版本中提取一个长数字,然后相互比较。 但是,这个数字需要有以下格式: 两位数字表示大调、小调和修订,四位数字表示构建。

如何提取版本号:

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.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());
}
}

我发现这个算法在互联网上似乎工作得很好。

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

}