Some questions seem to come and go in waves. Recently, several people asked me about versioning .NET assemblies. There are at least four attributes int the BCL that allow you to specify version information for a .NET assembly: AssemblyVersionAttribute, AssemblyFileVersionAttribute, ComCompatibleVersionAttribute and AssemblyInformationalVersionAttribute. How should you use them?
The Assembly Version (AssemblyVersionAttribute) reflects the version of the specification of the assembly. It changes when the API changes (types or methods added, modified or removed), or when the semantics of the API change (a method now does something functionally different). When neither of these conditions are met, existing clients will be compatible with the new “version”, and the Assembly Version should not change.
The File Version (AssemblyFileVersionAttribute) reflects the distribution. It changes when the binary image of the Assembly changes, even when the Assembly Version does not. Typically, this is the result of bug fixes or internal optimizations.
While in theory the File Version allows any string to be used as a value, it is highly recommended to use a four number version string, according to the same syntax and semantics as the assembly version.
These version numbers consist of four numbers in the range 0 to 65534. The four values indicate:
- Major Version: change when features have been modified or removed.
- Minor Version: change when features have been added or Major version changed.
- Build number: change when bugs have been fixed or Minor Version changed.
- Revision number: change when non-functional improvements were made or the Build number changed.
When using a correct numbering scheme, compatibility between versions is as follows:
- A change in major version: the new version is not compatible with the old version.
- A change in minor version (but not in major version): the new version is backwards compatible with the old version, but not forward compatible. Applications using the new features don’t work with the old version, but old applications do work with the new version.
- A change in build number (but not in major or minor version): the new version is binary compatible with the old version, both forward and backward. A change in behavior may be observed as a result of a bug fix.
- A change in revision number only: the new version is binary compatible with the old version, both forward and backward. Only non-functional changes in behavior, such as changed performance characteristics, may be observed as a result of non-functional changes.
When one of these numbers is modified, typically all lower level numbers are reset to zero.
If an assembly exposes types defined in another assembly in its public API, and the other assembly’s Assembly version changes, then the Assembly version of this assembly should change as well. If the other assembly has increased its major version, increase this assembly’s major version as well. Avoid exposing types defined in third-party assemblies, in order to limit this problem.
|Changed version number
||Features changed or removed
||Forward and backward
||Forward and backward
Typically, the Major Version and Minor Version are the same in the Assembly Version and in the File Version. The Assembly Version will have the build number and revision number equal to zero, while the File Version is updated with every bug fix or non-functional improvement.
When the Assembly Version includes the Minor version, strong named assemblies compiled against the previous version will not pick up the new version from the GAC. You need to recompile the client assemblies against the new version, configure the client applications, or create a publisher policy. Likewise, assemblies compiled against the new (minor) version won't accidentally pick up the old version.
When you leave the build and revision numbers equal to zero in the Assembly version, you don't need to do anything when you want to deploy a bug fix or internal optimization.
The VB and C# compilers generate an operating system resource in the assembly file, such that several of these attributes show up in the Version tab of the file properties dialog box. Please note that the C++ compiler does not do this. In C++, a version resource needs to be added manually by the developer, and the developer must manually synchronize its contents with the assembly level attributes.
Typically, there should be no reason to include a ComCompatibleVersionAttribute or AssemblyInformationalVersionAttribute.