In Visual Studio, there are at least three different types of class libraries you can create:
While the first is what we've been using for years, a major point of confusion I've been having is when to use the .NET Standard and .NET Core class library types. I've been bitten by this recently when attempting to multi-target different framework versions, and creating a unit test project.
So, what is the difference between Class Library (.NET Standard) and Class Library (.NET Core), why do both exist, and when should we use one over the other?
When should we use one over the other?
The decision is a trade-off between compatibility and API access.
Use a .NET Standard library when you want to increase the number of applications that will be compatible with your library, and you are okay with a decrease in the .NET API surface area your library can access.
Use a .NET Core library when you want to increase the .NET API surface area your library can access, and you are okay with allowing only .NET Core applications to be compatible with your library.
For example, a library that targets .NET Standard 1.3 will be compatible with applications that target .NET Framework 4.6, .NET Core 1.0, Universal Windows Platform 10.0, and any other platform that supports .NET Standard 1.3. The library will not have access to some parts of the .NET API, though. For instance, the Microsoft.NETCore.CoreCLR
package is compatible with .NET Core, but not with .NET Standard.
What is the difference between Class Library (.NET Standard) and Class Library (.NET Core)?
Compatibility: Libraries that target .NET Standard will run on any .NET Standard compliant runtime, such as .NET Core, .NET Framework, Mono/Xamarin. On the other hand, libraries that target .NET Core can only run on the .NET Core runtime.
API Surface Area: .NET Standard libraries come with everything in NETStandard.Library
, whereas .NET Core libraries come with everything in Microsoft.NETCore.App
. The latter includes approximately 20 additional libraries, some of which we can add manually to our .NET Standard library (such as System.Threading.Thread
) and some of which are not compatible with the .NET Standard (such as Microsoft.NETCore.CoreCLR
).
Also, .NET Core libraries specify a runtime and come with an application model. That's important, for instance, to make unit test class libraries runnable.
Why do both exist?
Ignoring libraries for a moment, the reason that .NET Standard exists is for portability; it defines a set of APIs that .NET platforms agree to implement. Any platform that implements a .NET Standard is compatible with libraries that target that .NET Standard. One of those compatible platforms is .NET Core.
Coming back to libraries, the .NET Standard library templates exist to run on multiple runtimes (at the expense of API surface area). Conversely, the .NET Core library templates exist to access more API surface area (at the expense of compatibility) and to specify a platform against which to build an executable.
Here is an interactive matrix that shows which .NET Standard supports which .NET implementation(s) and how much API surface area is available.