在C#中如何将程序集版本获取为整数?

4

我可以将其作为字符串获取:

Assembly.GetExecutingAssembly().GetName().Version()  

如何将此数字转换为整数?


示例输入:

8.0.0.1

预期输出:

8001


第一步 - 你得到的字符串是什么? - Adam Ralph
你如何假设地将 A.B.C.D 转换为整数? - annakata
我只想将字符串中的所有数字连接起来。 - Sasha
4
请考虑案例8.1.11.0和8.11.1.0。 - Adam Ralph
你真正想做什么?版本比较吗?在Version类中有一种内置的方法。 - VVS
显示剩余4条评论
11个回答

12

如果你真的必须进行这种转换,那么你应该至少为每个版本部分保留足够的数字位数

主版本、次版本和修订版本需要两位数字,构建版本需要四位数字:

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

Debug.Assert(version.Major >= 0 && version.Major < 100)
Debug.Assert(version.Minor >= 0 && version.Minor < 100)
Debug.Assert(version.Build >= 0 && version.Build < 10000)
Debug.Assert(version.Revision >= 0 && version.Revision < 100)

long longVersion = version.Major * 100000000L + 
                   version.Minor * 1000000L + 
                   version.Build * 100L + 
                   version.Revision;

int intVersion  = (int) longVersion;

Debug.Assert((long)intVersion == longVersion)

需要注意,这种方法仍然无法处理某些奇特的版本!

别想着用版本号21.47.4836.48 :)

编辑: 添加了断言。


使用主要/次要/构建/修订属性而不是解析版本字符串,这样做会得到+1分。正如你所指出的,对于大数值来说,解析版本字符串可能会失败(包括溢出)。 - Joe

3
他们是数字,所以您可以将它们转换为字符串,并将它们堆叠在一起:
Version v = Assembly.GetExecutingAssembly().GetName().Version;
string compacted = string.Format("{0}{1}{2}{3}", v.Major, v.Minor, v.Build, v.Revision);
int compactInt = int.Parse(compacted);

当每个组件小于十时,这种方法当然很有效。但是一旦超过十,你就无法确定实际版本。字符串“12345”可以是1.23.4.5或12.3.4.5或1.2.34.5或......
如果你知道它们都在十以下,你可以按数字顺序排列:
Version v = Assembly.GetExecutingAssembly().GetName().Version;
int compactInt = v.Major * 1000 + v.Minor * 100 + v.Build * 10 + v.Revision;

如果你不知道这个,那么就会更加复杂一些,但是你仍然可以在不创建字符串并解析它的情况下完成。这样会快一点,但需要10到20行代码。


2
另一种选择是将其视为4字节整数。 每个版本部分(主要版本、次要版本、构建版本、修订版本)的值将限制在0-255之间,但您可以将版本打包到整数值中。
这可以避免8.10.0.0大于9.0.0.0(81,000 > 9,000)的问题。
    /// <summary>
    ///  
    /// Converts a version string in the format of 
    /// [major].[minor].[build].[revision] into an integer.
    ///  
    /// </summary>
    /// <remarks>
    /// Each part of the build number must be within the range of 0 to 255.
    /// </remarks>
    /// <param name="version"> The version to convert to an integer. </param>
    /// <returns>
    /// The integer representation of the <paramref name="version"/>.
    /// </returns>
    public static int VersionToInt( string version ) {
        // Parse version number
        var versionParts = version.Split( '.' );
        if ( versionParts.Length != 4 ) {
            throw new ArgumentException( "Invalid version number; invalid number of version parts, expected 4 (major.minor.build.revision)",
                                         "version" );
        }

        // Convert parts to bytes
        byte major, minor, build, revision;
        if ( !byte.TryParse( versionParts[0], out major ) ) {
            throw new ArgumentException( "Invalid version number; invalid major number", 
                                         "version" );
        }
        if ( !byte.TryParse( versionParts[1], out minor ) ) {
            throw new ArgumentException( "Invalid version number; invalid minor number",
                                         "version" );
        }
        if ( !byte.TryParse( versionParts[2], out build ) ) {
            throw new ArgumentException( "Invalid version number; invalid build number", 
                                         "version" );
        }
        if ( !byte.TryParse( versionParts[3], out revision ) ) {
            throw new ArgumentException( "Invalid version number; invalid revision number", 
                                         "version" );
        }

        // Combine bytes into an integer
        var versionInteger = 0;
        versionInteger |= major << 24;
        versionInteger |= minor << 16;
        versionInteger |= build << 8;
        versionInteger |= revision;

        return versionInteger;
    }

当处理 VSTS 版本号和基于整数且不能超过 2100000000 的 Android VersionCodes 时,这非常有帮助。所有其他示例都只使用第四个版本部分 - 但如果您有 ALM 分支策略,则对 Android 来说这是不好的! - oatsoda

1

以下代码“可行”:

string version = "8.0.0.1";
int versionNumber = int.Parse(version.Replace(".", ""));

然而,版本8.0.11.0和8.0.1.10之间没有任何区别!


谢谢,那个可行。我刚意识到我需要的是次要和主要版本号。基本上,如果它是8.0.1.0,我需要将其转换为801000。 - Sasha
字符串版本 = "9.0.1.0"; 整数版本号 = int.Parse(版本 + "0.0".Replace(".", "")); - Sasha

1
你可以使用 string.Split('.') 方法,然后迭代并使用 int.parse() 方法。

+1 分割。这样可以让您根据自己的喜好格式化最终的整数,因为您似乎对最终结果的外观很在意。 - Will Eddins

0
我会这样做:
Integer.Parse(Assembly.GetExecutingAssembly().GetName().Version().ToString().Replace(".", ""))

我改正了。


你不能将字符串转换为整数。你必须解析它。可以使用Int.Parse或Convert.ToInt32来执行。 - Guffa
你不能仅仅去掉“.”字符,因为例如(正如AdamRalph和其他人指出的那样),从版本8.1.11.0和版本8.11.1.0中去掉句点将导致相同的整数值:81110。 - Adam Porad

0

试试这个:

Version v = Assembly.GetExecutingAssembly().GetName().Version;
long s = long.Parse(v.Major.ToString("0000") + v.MajorRevision.ToString("0000") + v.Minor.ToString("0000") + v.MinorRevision.ToString("0000"));

0

你也可能遇到这样的情况,即某个程序集的版本为0.0.1.1,然后版本号看起来像是11。显然不是期望的结果。


0
你试图解决的问题是什么?你是在检查某个库的运行版本是否大于或等于某个已知的无错误版本吗?如果是这样,正确的做法不是将由“.”分隔的数字字符串视为单个数字,而是逐个将它们与目标进行比较。

在这种情况下,您可以直接比较版本对象。比较运算符已经重载以处理版本对象。 - Guffa

0
与此方法不同,假设每个版本字符串元素都小于255,您可以将每个元素作为32位无符号整数中的一个字节。这样做可能不太容易阅读,但将确保在版本比较中如果V1 < V2,则整数转换f(V1) < f(V2)。

大多数情况下,构建为4位数字。 - VVS
在这种情况下,我们可以从主/次版本中提取一些比特,将构建范围扩展到2 ^ 14奇数。 - Adam Wright

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接