Recently a conversation made me think about the current state of .NET. Someone from outside the .NET community asked me if .NET ran on Linux. The answer is that .NET has great cross platform support, running on Windows, Linux, maxOS, Android, iOS, WebAssembly, but I can see why someone from outside .NET might think that it didn't.
There are still a few nuances when it comes to cross platform support in the .NET world, but I think that's true of most development platforms today. This post aims to explain those nuances.
I looked for a good post to explain the state of .NET to someone outside the .NET community, but I had trouble finding one. For example, the Microsoft .NET blog does a great job of explaining the changes coming up in .NET 5 to the .NET community, but it assumes that you already know the difference between .NET Framework and .NET Core which I think most people outside of .NET have no idea about.
.NET Today
.NET is a platform for developing software. There are two parts to .NET. The first part of .NET is a virtual machine for executing programs written in an abstract assembly language, the virtual machine is called the Common Language Runtime (CLR) and the assembly language is called Intermediate Language (IL). The second part is a large standard class library called the Framework Class Library (FCL) - often referred to as the Base Class Library (BCL) in docs. Together the CLR and FCL make up .NET.
An important goal for the CLR was to allow the smooth interoperation of many programming languages. This achieved via .NET assemblies, these are class libraries that contain binary IL and also enough meta data for a compiler to be able to consume them directly. This means that a program executing on the CLR can be made up of assemblies that are written in different programming languages. The only difference between executables and libraries in .NET is that executables have an entry point specified. Therefore, any compiler that targets the CLR and can produce assemblies, can both create class libraries that are consumable by any other .NET compiler and create executables from assemblies that may have been written in other languages.
Assemblies can be created from the text form of the IL assembly language using the IL Assembler, but it's much more common to use a programming language to create assemblies. There are many programming languages that can create .NET assemblies, the most common being C#, F# and Visual Basic.
We'll take a quick tour of the features of the CLR and then talk about the implementations of the CLR and FCL that exist today.
The usual way that code is executed in the CLR is by 'just in time' (JIT) compilation, meaning each method is compiled from byte codes to native machine code just before the method is executed. There are some version of the CLR support 'ahead of time' (AOT) compilation of .NET assembles and even interpretation of IL, but the main focus of the CLR has been JIT, so AOT compilation support is not as fully developed as it might be and only fairly idiosyncratic version of the CLR offer IL interpretation.
The CLR is garbage collected environment, meaning that the programer does not need to manage the deallocation of memory directly, a garbage collector (GC) will decide whether memory is still in use or not and de-allocate it, if it detects it's not in use. Different version of the CLR have different GC algorithms, but the most commonly used one is tracing garbage collection with additional heuristics to try and optimize memory management in a number of different scenarios.
Despite the CLR using GC it also provides many mechanisms to allow the programmer to control memory allocation and deallocation themselves. It is possible, with considerable effort, to write programs that never, at or least very rarely, invoke the GC.
Other features available in the CLR include the ability to easily invoke native code and structured exception handling.
Standards specifying the behavior of both CLR and FCL exist and have been ratified by both Ecma International (ECMA) standards and International Organisation for Standardisation (ISO). The current version of ISO standards are ISO/IEC 23271:2012 and ISO/IEC 23270:2006.
If you are interested in doing .NET development today. There are three different version of the CLR you can choose from. These are:
Name | Open Source | OS Support |
---|---|---|
.NET Framework | No | Windows |
.NET Core | Yes | Windows, Linux, macOS |
Mono | Yes | Windows and any *nix like OS |
There are other implementation of the CLR available, but these three are being actively developed and are fully supported today.
While having to choose between three different implementations of the sample platform isn't ideal, it is really no different than having to choose between CPython and PyPY or GCC, Microsoft Visual C++ or Intel C.
In the .NET world there is a high degree of compatibility between the three CLR implementations I talk about. The CLR implementations are now being developed with a high degree of cooperation between the teams maintaining them and are synchronizing their release cycles.
Code can generally be cross compiled between these three different CLR implementations and sometimes binaries targeting CLR implementation can be used by another CLR implementation without any change. The pain points when trying to port code from one CLR implementation tend to be the libraries. There are small variations in the FCL for each implementation, while effort has been made to keep the variations to a minimum, even a missing class can cause a lot of pain, if you depend on that class a lot from client code. Some libraries may only work on some OSs because they take dependencies on the features only available in that particular OS.
To dig a little deeper into whether an implementation is open source or not, ".NET Framework" isn't open source, parts of the source code are available, but it isn't available under an open source license and it does not accept pull requests. From their beginning both "Mono" and ".NET Core" have been fully open source. They are both hosted on github.com now (which admittedly is owned by Microsoft these days). They both accept pull requests.
In terms of OS support ".NET Framework" just supports Windows, ".NET Core" supports Windows, Linux and MacOS, while "Mono" has been ported to a large range of *nix like operating systems and so provides support for mobile development by being able to create apps for Android and iOS.
.NET Tomorrow
The .NET teams have announced that in the next version of .NET there will be only two version implementations of the CLR. .NET core will be renamed and .NET and the two code bases will be merged to ensure as much as possible from the .NET Framework is present in the new .NET. This will mean from the release of .NET 5, the main choice of CLR implementations will be:
Name | Open Source | OS Support |
---|---|---|
.NET | Yes | Windows, Linux, macOS |
Mono | Yes | Windows and any *nix like OS |
For the .NET 5 release further work will be done to make .NET and Mono more compatible, with the aim being to make it easy to move code between the two platforms, so the developer's choice is do they want a CLR that is less configurable and supports a few operating systems very well, in that case use .NET or do they want a CLR that is very configurable and can run across a huge range of operating systems, in that case use Mono.
Summary
We have a high level overview of what .NET is and the features that make it up. We've seen that at its core .NET is a software runtime called the CLR that will execute an abstract assembly language called IL. We've seen that the CLR is an open standard with several different implementation and had a quick look at the differences between the most relevant implementations. We have seen that although one CLR implementation is closed source software and only runs on Windows, the other two major CLR implementations are fully open source and between them have support for a wide variety of OSs. The current direction of the project is towards more parts being open source.
Acknowledgements
I like to thank nieve, Bouillier Clément, Marco Rossignoli and Mendel Monteiro for their comments and corrections.
I have drawn significant influence Wikipedia's many articles on .NET, I would like to thank the authors of these articles. The idea of this article was present a simplified version of the extensive details available on Wikipedia.