A software library is rarely complete in version 1.0. Good libraries evolve over time, adding features, fixing bugs, and improving performance. It is important that you can release new versions of a .NET library, providing additional value with each version, without breaking existing users.
For information about handling breaking changes between versions, see Breaking changes.
A .NET library has many ways to specify a version. These versions are the most important:
NuGet package version
The NuGet package version is displayed on NuGet.org, the Visual Studio NuGet package manager, and is added to source code when the package is used. The NuGet package version is the version number users will commonly see, and they'll refer to it when they talk about the version of a library they're using. The NuGet package version is used by NuGet and has no effect on runtime behavior.
The NuGet package identifier combined with the NuGet package version is used to identify a package in NuGet. For example,
11.0.2. A package with a suffix is a pre-release package and has special behavior that makes it ideal for testing. For more information, see Pre-release packages.
Because the NuGet package version is the most visible version to developers, it's a good idea to update it using Semantic Versioning (SemVer). SemVer indicates the significance of changes between release and helps developers make an informed decision when choosing what version to use. For example, going from
2.0 indicates that there are potentially breaking changes.
✔️ CONSIDER using SemVer 2.0.0 to version your NuGet package.
✔️ DO use the NuGet package version in public documentation as it's the version number that users will commonly see.
✔️ DO include a pre-release suffix when releasing a non-stable package.
Users must opt in to getting pre-release packages, so they will understand that the package is not complete.
The assembly version is what the CLR uses at run time to select which version of an assembly to load. Selecting an assembly using versioning only applies to assemblies with a strong name.
The .NET Framework CLR demands an exact match to load a strong-named assembly. For example,
Libary1, Version=126.96.36.199 was compiled with a reference to
Newtonsoft.Json, Version=188.8.131.52. .NET Framework will only load that exact version
184.108.40.206. To load a different version at run time, a binding redirect must be added to the .NET application's config file.
Strong naming combined with assembly version enables strict assembly version loading. While strong naming a library has a number of benefits, it often results in run-time exceptions that an assembly can't be found and requires binding redirects in
web.config to be fixed. In .NET Core, assembly loading is more relaxed. The .NET Core runtime automatically loads assemblies with a higher version at run time.
✔️ CONSIDER only including a major version in the AssemblyVersion.
e.g. Library 1.0 and Library 1.0.1 both have an AssemblyVersion of
220.127.116.11, while Library 2.0 has AssemblyVersion of
18.104.22.168. When the assembly version changes less often, it reduces binding redirects.
✔️ CONSIDER keeping the major version number of the AssemblyVersion and the NuGet package version in sync.
The AssemblyVersion is included in some informational messages displayed to the user, e.g. the assembly name and assembly qualified type names in exception messages. Maintaining a relationship between the versions provides more information to developers about which version they are using.
❌ DO NOT have a fixed AssemblyVersion.
While an unchanging AssemblyVersion avoids the need for binding redirects, it means that only a single version of the assembly can be installed in the Global Assembly Cache (GAC). Also, the applications that reference the assembly in the GAC will break if another application updates the GAC assembly with breaking changes.
Assembly file version
The assembly file version is used to display a file version in Windows and has no effect on run-time behavior. Setting this version is optional. It's visible in the File Properties dialog in Windows Explorer:
✔️ CONSIDER including a continuous integration build number as the AssemblyFileVersion revision.
For example, you are building version 1.0.0 of your project, and the continuous integration build number is 99 so your AssemblyFileVersion is 22.214.171.124.
✔️ DO use the format
Major.Minor.Build.Revision for file version.
While the file version is never used by .NET, Windows expects the file version to be in the
Major.Minor.Build.Revisionformat. A warning is raised if the version doesn't follow this format.
Assembly informational version
The assembly informational version is used to record additional version information and has no effect on runtime behavior. Setting this version is optional. If you're using Source Link, this version will be set on build with the NuGet package version plus a source control version. For example,
1.0.0-beta1+204ff0a includes the commit hash of the source code the assembly was built from. For more information, see Source Link.
<AssemblyInformationalVersion>The quick brown fox jumped over the lazy dog.</AssemblyInformationalVersion>
Older versions of Visual Studio raise a build warning if this version doesn't follow the format
Major.Minor.Build.Revision. The warning can be safely ignored.
❌ AVOID setting the assembly informational version yourself.
Allow SourceLink to automatically generate the version containing NuGet and source control metadata.