Microsoft .NET program manager Immo Landwerth has set out the latest summary of how to write code that targets more than one version of the platform.
The long-standing problem is that the multitude of different .NET runtimes and platforms causes problems for anyone writing code that targets more than one, such as developers wanting to share non-visual code, or creating libraries for wide use.
The issue came to a head when Microsoft acquired Xamarin in 2016, making official Xamarin's flavour of .NET (based on the open-source Mono implementation) and its support for iOS and Android. At the time, Silverlight and Windows Phone were also still a thing. How could developers share code between all these platforms?
Microsoft came up with the idea of Portable Class Libraries (PCLs) in 2012. A PCL project created a DLL that specified which targets it supported, such as .NET Framework, Silverlight, and Windows Phone. After the Xamarin acquisition, the need for PCLs was even more pressing, and the PCL concept was expanded and refined.
It was not long before the company decided PCLs were not good enough. In September 2016, Landwerth introduced .NET Standard, explaining: ".NET Standard is a set of APIs that all .NET platforms have to implement. This unifies the .NET platforms and prevents future fragmentation." PCLs were faulty, he said. "The set of available APIs is the result of the intersection between the selected platforms, which doesn't always produce an API surface you can easily predict."
There were still fudges. The idea of .NET Standard was to specify a range of APIs implemented across all the .NET versions that support that standard. This turned out to be too restrictive, because of platform-specific APIs. Some key APIs, like those supporting the Windows Registry, were kept in the standard, but will throw a
PlatformNotSupportedException message if used on non-Windows platforms. Still, PCLs were out, .NET Standard was in.
Microsoft has now said it will not be updating .NET Standard. ".NET 5 improves code sharing and replaces .NET Standard," Landwerth said in a new post.
In a document on GitHub Landwerth described the problem with Target Framework Names (TFMs) in .NET.
There are too many, he said. ".NET Framework, .NET Compact Framework, Silverlight, .NET Micro Framework, .NET Portable Class Libraries, .NET for Windows Store, .NET Native, .NET Core" and then the Mono/Xamarin variants.
When .NET Standard turned up, it improved matters in one way but made it worse in another.
"We've simplified the world with .NET Standard, in that class library authors don't have to think about all the different 'boxes' that represent different implementations of .NET... Ironically, this resulted in us having to add yet another box, namely .NET Standard," he acknowledged.
Now there will be a new approach to TFMs. The base will be
net5.0 and then there will be other variants that inherit from it, like
net5.0-windows. TFMs can be further refined with a version number, like
net5.0-ios12.0. When .NET 6.0 rolls out next year, these will be updated to
net6.0 and so on. Unlike .NET Standard, these are not specifications. "Since there is no difference between the standard and its implementation, you'll be able to take advantage of new features much quicker than with .NET Standard," said Landwerth.
What was wrong with .NET Standard? It was too slow to update, said Landwerth, requiring an editorial board to approve new versions. Mapping .NET Standard versions to the platforms that implemented them was complex. And the fudge around platform-specific APIs were "like 'landmines' – the code compiles without errors and thus appears to be portable to any platform, but when running on a platform that doesn't have an implementation for the given API, you get runtime errors," he said.
What happens now if you use platform-specific APIs like those calling the Windows Registry? Developers will get a compiler warning, said Landwerth, unless they use a
SupportedOsPlatform attribute, or guard the code with conditions like:
.NET now runs in the browser thanks to Blazor WebAssembly, and here developers can use
OperatingSystem.IsBrowser – because today's web browsers are almost OSes in themselves.
That said, .NET Standard has not quite gone away. The Windows-only .NET Framework supports .NET Standard 2.0 and this will not be updated. Libraries designed to work in both .NET Framework and .NET 5.0 should target .NET Standard 2.0, said Landwerth. There should not be much need though for .NET Standard 2.1. "Most code can probably skip .NET Standard 2.1 and go straight to .NET 5," he said.
The problem is tough but what riles developers is that Microsoft has changed its approach so many times.
"I want to believe. I just hope we're not hearing about yet another story in a few years," said Microsoft program manager Glenn Block, who works on Microsoft Graph. If that is an internal perspective, what are the rest of us to make of it? ®