Key Takeaways Comphrensive tooling is available for .NET developers on any platform: VS Code, Visual Studio for Mac, and traditional Visual Studio on Windows.

.NET Standard offers a way to provide developers with guidance as to the APIs available in a given .NET platform

.NET Core developers can target macOS, Linux, Windows, or all three

.NET Core is open source and being developed "in the open" by Microsoft

.NET Framework remains supported by Microsoft for developers that need to target Windows specifically

Once upon a time, there was a single .NET, known as the .NET Framework. If you wanted to write .NET applications, you targeted the .NET Framework, and life was simple. After a few years, there came a Cambrian explosion of .NET varieties (let’s call it a ".NET explosion"): .NET Framework Client Profile, .NET Compact Framework, .NET Micro Framework, Windows Runtime, Universal Windows Platform, Mono, Xamarin, .NET Core, and .NET Standard. Like the organisms that came out of the Cambrian explosion, many of the .NET varieties that came out of the .NET explosion eventually became extinct: They are either no longer being supported, or no longer being updated. Other varieties occupy very narrow and specialized ecological niches. A few varieties, the ".NET survivors," thrived and are currently going strong, having been developed for specific reasons and uses. The goal of this article is not to go too deeply into the technical details of the different .NETs; plenty of technical resources are available, and pointers to some of them are provided. Rather the goal here is to answer a simple question: Which variety of .NET should you use in a given situation?

.NET Framework

The implementation of .NET known as the .NET Framework is the original .NET, from which all others descended. It’s the largest version of .NET, both in the number of APIs supported, and in the size of the download. Many versions of .NET Framework have been released over the years, each one adding new APIs and other features. The .NET Framework is developed and supported by Microsoft, and it only runs on Windows machines.

If your application is only ever going to run on Windows, you should probably target the .NET Framework. Since it supports the largest set of APIs, you’re much less likely to have to worry about whether you can easily accomplish some complex task if you target the .NET Framework. However, if you want your application to run on platforms other than Windows from the start, or if it’s possible that you might want the application to run on non-Windows platforms in the future, then you should probably consider a different .NET variety.

Mono

Mono is an open-source implementation of .NET intended to be compatible with the .NET Framework, but that runs on lots of different platforms, including Windows, macOS, and Linux. The project was started by enthusiasts, led by Miguel de Icaza, who believed that the benefits of .NET should be enjoyed on other platforms besides Windows, and that the best way to accomplish this was through an open-source effort. The stewardship of Mono has moved from one company to another, as de Icaza moved: from Ximian to Novell to Xamarin to Microsoft.

Mono’s coverage of .NET’s APIs is not complete, but it’s pretty good. Porting from .NET Framework to Mono is fairly easy, and, where API coverage doesn’t exist, relatively easy workarounds exist.

Mono is still a viable option for cross-platform .NET implementation, although Microsoft seems to be devoting most of its cross-platform .NET efforts to .NET Core, so you should probably consider that if you’re looking to the future. Also, Xamarin/Microsoft now seems to be focusing most of their Mono efforts on the Xamarin platform and support for iOS and Android, although Mono support for desktop and server platforms seems to be active, too. In summary, if you have a .NET Framework application for Windows, and you now want your application to support Windows, macOS, Linux, BSD, and a bunch of other platforms but you want to spend a minimal amount of effort on converting your .NET application to run on many platforms, Mono may still be your best bet.

.NET Core

.NET Core is another open-source cross-platform .NET implementation, this time stewarded by Microsoft from its inception. It also supports Windows, macOS, and Linux. Initially, .NET Core appeared to be a somewhat lightweight implementation: powerful enough to support ASP.NET and console apps and not much else. Later, it seemed to expand to support a subset of APIs that could be easily supported on Windows, macOS, and Linux, while leaving out support for things like the Registry, which were Windows-specific. At this point, API coverage seems to have expanded further, so that it’s almost like a reboot of the .NET Framework, trying to be as complete as possible on multiple platforms while also avoiding APIs that Microsoft appears to wish that it no longer had to support (for example, .NET remoting). UI APIs like Windows Forms and WPF are also not supported (Microsoft has announced that the next version of .NET Core will have support for desktop application programming, including Windows Forms and WPF, but this will only work when the applications are running on Windows).

Since .NET Core seems to be the future when it comes to cross-platform .NET, I would recommend targeting it if you’re writing new applications that you want to run on Windows, macOS, or Linux, as long as you don’t require a non-web GUI (since Windows Forms and WPF are unavailable). It might not have as many APIs as .NET Framework, but if you’re starting from scratch with a new application, you can design with this smaller API footprint in mind. However, if you want to migrate an existing .NET Framework to cross-platform support, migrating to .NET Core could be a heavy lift, since there may be crucial APIs that you need that it doesn’t support. Note that Microsoft has tried to ease the way with offerings like the Windows Compatibility Pack, which provides support for Windows-specific APIs that don’t exist in .NET Core. However, if you use those, you’re still locked into Windows, at least until .NET Core offers those APIs itself, or you rewrite your code to remove dependence on them.

.NET Standard

.NET Standard is another effort to support .NET use across multiple platforms. Unlike .NET Framework, Mono, and .NET Core, it’s not a complete package with runtimes and a library. Rather, it’s a specification of APIs that should be supported on a .NET implementation — particularly .NET Framework, .NET Core, and Xamarin (the Microsoft-supported Mono offshoot that’s targeted toward iOS, Android, and macOS). The intention is that any library implemented for .NET Standard should be able to work in any application built for any of the .NET platforms. .NET Standard supports only libraries, not applications, and it’s designed so that you can write libraries that will work anywhere.

.NET Standard 2.0, the latest version, has a very broad API coverage, but numerous missing APIs still exist. It pretty much covers .NET Core, but leaves out a fair amount of .NET Framework. Of course, there’s nothing keeping you from targeting those missing APIs, but then you’re targeting .NET Framework, not .NET Standard, and you’re locked into it until you get rid of those API calls.

If you’re writing a new set of libraries, I would recommend trying to target .NET Standard. If you do, your libraries will run on .NET Framework, .NET Core, or Xamarin, with no additional effort. You will of course have to create apps targeted for the specific .NET variants, but if you make the apps small enough, including the GUI-based classes that aren’t supported in .NET Standard, and put most of the functionality in the shared libraries, then you should be able to get the benefits of cross-platform support for as much of your code as possible. Migrating existing .NET Framework code again may be more involved due to the lack of certain APIs, but even there you may be able to migrate as much code as possible to .NET Standard libraries and keep the platform-specific code isolated. There may be opportunities to make use of your .NET Standard libraries in cross-platform scenarios, and you can, over time, spend the additional effort on migrating the remaining code to .NET Standard.

A Brief Note on Tooling

For a while each .NET variant had its own dedicated development tools. Visual Studio was for .NET Framework, MonoDevelop was for Mono, and Visual Studio Code was (mostly) for .NET Core. More recently, the lines have blurred. In addition to .NET Framework, you can now use Visual Studio to develop for Xamarin, .NET Core and .NET Standard. Visual Studio Code was originally a source code editor but has now become a much more complete development environment and can be used to develop for .NET Framework or .NET Core. Xamarin Studio (based on MonoDevelop) has been deprecated for Windows (they encourage you to use Visual Studio) but has now been adapted as Visual Studio for Mac, where it can be used to develop for Xamarin or .NET Core. So, unless you’re doing hardcore .NET Framework development (in which case you should use Visual Studio), you can really pick your environment based on other needs.

Conclusion

The .NET explosion produced many .NET variants, some of which are extinct, others of which occupy a very narrow niche, and others of which are thriving. The .NETs that are thriving are similar enough that developers are often confused when they encounter them, and aren’t sure which one to use, but choosing between them is fairly straightforward. Use the original .NET Framework when you’re creating an application that will only ever run on Windows. Use Mono if you want your application to run on many platforms and you need API coverage approaching that provided by the full .NET Framework. (Mono is also a good development target if you’re migrating an existing .NET Framework application to other platforms besides Windows.) Target .NET Core if you’re creating cross-platform applications that can be built using .NET Core’s somewhat restricted API set. Finally, consider using .NET Standard to create libraries that can run on .NET Framework, .NET Core, or Xamarin, and isolate the platform-specific parts of your application, such as the user interface, in components targeted toward specific platforms.

About the Author

Dr. Wayne Citrin is CTO and cofounder of JNBridge, LLC, the leading provider of interoperability tools to connect Java and .NET frameworks. The architect of award-winning bridging technology JNBridgePro and JMS Adapters for .NET and BizTalk, Citrin has been solving Java and .NET interoperability issues since .NET’s beta days. Citrin has served as a leading researcher in programming languages and compilers, and was on the Computer Engineering faculty at the University of Colorado, Boulder.