Visual Studio 2012 has been out for a while now, I’ve been using it every day at work and I’m generally very happy with it. The biggest win is the performance, which is some much better than VS2010.
I’ve finally begun to get curious about the new stuff in VS2012. Visual Studio was delivered with .NET 4.5 a shiny new version of the .NET framework, that will allow developers to create “Metro” style apps (which for reason that are too silly to go into are no longer called Metro style apps, but we will continue to call them Metro style apps in this article as suitable name has yet to be found). You can also develop all the apps you used to be able to develop using .NET 4.5, such as WinForm, WPF, ASP.NET etc.
Metro style apps are the new style of application that will only run on Windows 8. They take up the full screen and are design to be used on touch screen tablet devices, though it is possible to use them from a device that isn’t touch screen. Metro style apps do not run on the Win34/Win64 Windows APIs we have come to know and love, they have their own APIs that are completely isolated from the classic Win34/Win64 Windows APIs. These new APIs are called WinRT, confusingly also the name of the version of Windows that runs on ARM based devices. WinRT will not load executable or .dll that target Win32/Win64, code must be compile specially for WinRT and applications cannot simple be download from the internet, they must be installed via the Windows Store (all though inevitably someone will find a way to hack there way round this restriction). The idea is that WinRT is locked down and completely isolated from the Win32/Win64 world to try and prevent the malware issues that plagued Win32/Win64 ‘anything goes’ world.
As we know the .NET framework is built on top of the Win32/Win64, so how does .NET 4.5 allow developers to create Metro style apps, while still allowing them create apps that run on Win32/Win64? The answer is simple, .NET 4.5 is not one framework but two:
- .NET 4.5 is an in-place update for .NET 4.0 used by Windows 7 applications, Windows 8 classic desktop mode, Mono-Mac, Mono-Linux etc.
- .NETCore 4.5 is the core implementation of .NET used by Windows Store apps written in .NET languages.
In VS2012 you know have the possibility to target either framework (or both in the case of building a library), it just depends on the project type you choose. So say you decided to create a .NET library, you now have the following choices:
- ‘Class Library’ project type, this creates a library that will target .NET 4.5 or any of the older ‘classic frameworks’
- ‘Portable Class Library’ project type, this creates a library that could potentially be used on any version of .NET, that is the ‘classic frameworks’, Silverlight, XBox and the new .NETCore 4.5 for Windows Store.
- ‘Class Library (Windows Store Apps)’ project type, this produces a class library that can only be used with .NETCore 4.5 for Windows Store.
I wanted to understand the difference between these projects types. I was particularly interested in what was the difference between the files produced ‘Class Library (Windows Store Apps)’ project type and the ‘Windows Runtime Component’ project type. I could seem to find a good explanation of this on the internet. So I open Visual Studio create project of each project type and then used ildasm to decompile each library so that I could compare them in WinMerge. For those who want to play with this for themselves I’ve uploaded by project here.
This is a summary of what I found and few other tip bits about .NET 4.5:
‘Portable Class Library’
These are very similar to the ‘Class Library’ project type. The only difference is that they create ‘retargetable’ reference to mscorlib. It looks something like this in the text version of IL:
.assembly extern retargetable mscorlib
.publickeytoken = (7C EC 85 D7 BE A7 79 8E ) // |.....y.
I’ve failed to find a good explanation of ‘retargetable’ keyword does in IL. It seems to be an old idea that’s been in available in IL for a good while as I found a reference to it on this site that was put together around 2005, which is actually an old readme file from an old distribution of F#, but it’s on the top results when you google for ‘extern retargetable mscorlib’. The site does offer a little inside what retargetable does:
“Retargetable binaries are neutral w.r.t. the publisher of particular referenced binaries. For example, a truly portable .NET program will be neutral w.r.t. the publisher of mscorlib - rather than picking up a dependency against the publisher of mscorlib used at compile-time. This means the program will bind to ANY assembly called "mscorlib", which is OK for mscorlib but is not necessarily such a good idea for other strong named assemblies.”
So there you go.
The programmer also gets a lot of choice about what can be targeted, they could choose to target .NET 4.5 and .NETCore 4.5 but not Silverlight, for example. To make this possible, Microsoft has create different “profiles”. Each profile allows to target a different set of frameworks for example “Profile1” lets you target .NET for Windows Store apps, .NET Framework 4, Silverlight 4, Windows Phone 7, XBox 360. Microsoft provide a set of reference assemblies that have all the methods that are common across all these frameworks, these live under: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.0\Profile\Profile1.
To add extra-meta data to the assembly the msbuild project produces a .cs file you’re temp directory and add this into the build. Here’s an example of the generated file:
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETPortable,Version=v4.0,Profile=Profile4", FrameworkDisplayName = ".NET Portable Subset")]
A full list of all the different profiles can be found here.
‘Class Library (Windows Store Apps)’ and ‘Windows Runtime Component’
These differ hugely from the ‘Class Library’ project type. In .NET Core mscorlib has been renamed to ‘System.Runtime’. So we seem this import at the top of both files:
.assembly extern System.Runtime
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
Confusingly the .winmd file also imports a version of mscorlib, whereas the .dll produced by ‘Class Library (Windows Store Apps)’ does not:
.assembly extern mscorlib
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
This seems to be because a .winmd file uses the definition of System.Object and System.Type from mscorlib whereas the .dll does not. I have no idea why this is.
For the ‘Class Library (Windows Store Apps)’ project type the renaming of mscorlib to System.Runtime accounts for most of the difference, (since the text IL format is very verbose and the assembly name and names is needed each time a type is referenced).
.class public auto ansi windowsruntime sealed beforefieldinit TestNet45.Class1
This implementation is completely implicit, no changes to the C# code where necessary. The implantation of the interface is accounts for most of the rest of the differences in the .winmd file and an ordinary .dll.
Another minor difference is that methods in .winmd file have attributes attached that specify the direction:
.method public hidebysig specialname rtspecialname
instance void .ctor([in] int32 a,
[in] string b,
[in] float64 c) cil managed
If you want to see a picture of the IL diffs you can see one here.
Other Differences in .NETCore 4.5
I’ve been trying to port some existing code to .NETCore 4.5 and keep it compatible with plain old .NET 4.5. There’s a couple of other difference that make this tricky. Firstly, .NETCore 4.5 assemblies are much more fine grain that their .NET 4.0 equivalents. Assemblies tend to only cover one namespace, so were as most of the System.Threading namespace as in mscorlib before it’s now split over several assemblies:
This can be a little annoying, trying to work out where stuffs gone, but I quickly got used to and it doesn’t make a huge difference. The second problem is much more annoying. It seems Microsoft has taken the opportunity to redesign some parts of the framework, System.Reflection has be heavily affect by this. The CLR team has a good blog post explaining the changes. While I understand the design rational, and even think the new API as are better some respect, it’s still very annoying porting code between the two models. Worse is trying to write code that is compatible with the two models, you end up drowning in ‘#if’ definitions. To add insult to injury some of the more powerful features, like the System.Reflection.Emit namespace have been completely removed.
Hope you’ve found this little tour of the difference between .NET 4.5 and .NETCore 4.5 useful. Happy hacking!