Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

.NET 4.5 is an in-place replacement for .NET 4.0


:P
On this page:

With the betas for .NET 4.5 and Visual Studio 11 and Windows 8 shipping many people will be installing .NET 4.5 and hacking away on it. There are a number of great enhancements that are fairly transparent, but it's important to understand what .NET 4.5 actually is in terms of the CLR running on your machine.

When .NET 4.5 is installed it effectively replaces .NET 4.0 on the machine. .NET 4.0 gets overwritten by a new version of .NET 4.5 which - according to Microsoft - is supposed to be 100% backwards compatible. While 100% backwards compatible sounds great, we all know that 100% is a hard number to hit, and even the aforementioned blog post at the Microsoft site acknowledges this. But there's so much more than backwards compatibility that makes this awkward at best and confusing at worst.

What does ‘Replacement’ mean?

When you install .NET 4.5 your .NET 4.0 assemblies in the \Windows\.NET Framework\V4.0.30319 are overwritten with a new set of assemblies. You end up with overwritten assemblies as well as a bunch of new ones (like the new System.Net.Http assemblies for example). The following screen shot demonstrates system.dll on my test machine (left) running .NET 4.5 on the right and my production laptop running stock .NET 4.0 (right):

VersionDifferences[8] 

Clearly they are different files with a difference in file sizes (interesting that the 4.5 version is actually smaller).

That’s not all. If you actually query the runtime version when .NET 4.5 is installed with with Environment.Version you still get:

4.0.30319

If you open the properties of System.dll assembly in .NET 4.5 you'll also see:

.NET VersionDialog

Notice that the file version is also left at 4.0.xxx.

There are differences in build numbers: .NET 4.0 shows 261 and the current .NET 4.5 beta build is 17379. I suppose you can use assume a build number greater than 17000 is .NET 4.5, but that's pretty hokey to say the least.

There’s no easy or obvious way to tell whether you are running on 4.0 or 4.5 – to the application they appear to be the same runtime version. And that is what Microsoft intends here. .NET 4.5 is intended as an in-place upgrade.

Compile to 4.5 run on 4.0 – not quite!

You can compile an application for .NET 4.5 and run it on the 4.0 runtime – that is until you hit a new feature that doesn’t exist on 4.0. At which point the app bombs at runtime. Say you write some code that is mostly .NET 4.0, but only has a few of the new features of .NET 4.5 like aync/await buried deep in the bowels of the application where it only fires occasionally. .NET will happily start your application and run everything 4.0 fine, until it hits that 4.5 code – and then crash unceremoniously at runtime. Oh joy!

You can .NET 4.0 applications on .NET 4.5 of course and that should work without much fanfare.

Version Detection

If you're building a .NET 4.5 application you do have some control over the runtime via YourApp.exe.config file options. Specifically you can specify that the app requires .NET 4.5 like this (thanks for Scott Hanselman pointing this out in the comments):

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0"
                      sku=".NETFramework,Version=v4.5" />
  </startup>
</configuration>

This works to ensure that the app will refuse to start on .NET 4.0 with an error on startup rather than waiting for something to blow up at runtime.

Likewise .NET 4.5 Web applications can use the targetFramework element on the <compilation> element:

<configuration>
  <system.web>
    <compilation debug="true"
                 strict="false"
                 explicit="true"
                 targetFramework="4.5" />
  </system.web>
</configuration>

This works fine for standalone applications and server, but it there's no solution for assemblies that are added to other projects. To a 4.0 project a .NET 4.5 assembly just looks like another 4.0 assembly.

For developers - especially component developers - this is also problematic since there's no built in way to determine whether you're running .NET 4.5. Environment.Version returns 4.0.

The following code block (dumped into the awsome LinqPad):

void Main()
{
    Environment.Version.ToString().Dump();
    Environment.Version.Build.Dump();
    Environment.Version.Revision.Dump();
    Environment.Version.Major.Dump();    
}

On .NET 4.0 it results in:

4.0.30319.269
30319
269
4

On .NET 4.5 it results in:

4.0.30319.17379
30319
17379
4

Pretty close, eh? Note however that the Revision number is high on .NET 4.5 - 17379 on the current build, while the .NET 4.0 revision number is 261. So if you really have to check specifically for .NET 4.5 you can use code like this:

// Define other methods and classes here
public static bool IsDotNet45()
{
    return Environment.Version.Major == 4 &&
           Environment.Version.Revision > 17000;
}

Others have commented (on Hanselman's post), that it's better to do feature detection for a new feature of .NET 4.5. The code Scott used uses a new class for .NET 4.5 plus some Reflection code to check for it:

public static bool IsNet45OrNewer()
{
    // Class "ReflectionContext" exists from .NET 4.5 onwards.
    return Type.GetType("System.Reflection.ReflectionContext", false) != null;
}

One advantage of this approach is that you're checking for a feature rather than a specific version, so in the future this code will continue to work so you effectively can future proof code.

Still it's pretty telling that we'll have to resort to this sort of chicanery just to figure out freaking version compatibility.

Different than .NET 3.0/3.5

Note that this in-place replacement is very different from the side by side installs of .NET 2.0 and 3.0/3.5 which all ran on the 2.0 version of the CLR. The two 3.x versions were basically library enhancements on top of the core .NET 2.0 runtime. Both versions ran under the .NET 2.0 runtime which wasn’t changed (other than for security patches and bug fixes) for the whole 3.x cycle. The 4.5 update instead completely replaces the .NET 4.0 runtime and leaves the actual version number set at v4.0.30319.

When you build a new project with Visual Studio 2011, you can still target .NET 4.0 or you can target .NET 4.5. But you are in effect referencing the same set of assemblies for both regardless which version you use. What's different is the compiler used to compile and link your code so compiling with .NET 4.0 gives you just the subset of the functionality that is available in .NET 4.0, but when you use the 4.5 compiler you get the full functionality of what’s actually available in the assemblies and extra libraries. It doesn’t look like you will be able to use Visual Studio 2010 to develop .NET 4.5 applications.

Good news – Bad news

Microsoft is trying hard to experiment with every possible permutation of releasing new versions of the .NET framework apparently. No two updates have been the same. Clearly updating to a full new version of .NET (ie. .NET 2.0, 4.0 and at some point 5.0 runtimes) has its own set of challenges, but doing an in-place update of the runtime and then not even providing a good way to tell which version is installed is pretty whacky even by Microsoft’s standards. Especially given that .NET 4.5 includes a fairly significant update with all the aysnc functionality baked into the runtime. Most of the IO APIs have been updated to support task based async operation which significantly affects many existing APIs.

To make things worse .NET 4.5 will be the initial version of .NET that ships with Windows 8 so it will be with us for a long time to come unless Microsoft finally decides to push .NET versions onto Windows machines as part of system upgrades (which currently doesn’t happen). This is the same story we had when Vista launched with .NET 3.0 which was a minor version that quickly was replaced by 3.5 which was more long lived and practical.

People had enough problems dealing with the confusing versioning of the 3.x versions which ran on .NET 2.0. I can’t count the amount support calls and questions I’ve fielded because people couldn’t find a .NET 3.5 entry in the IIS version dialog. The same is likely to happen with .NET 4.5. It’s all well and good when we know that .NET 4.5 is an in-place replacement, but administrators and IT folks not intimately familiar with .NET are unlikely to understand this nuance and end up thoroughly confused which version is installed.

It’s hard for me to see any upside to an in-place update and I haven’t really seen a good explanation of why this approach was decided on. Sure if the version stays the same existing assembly bindings don’t break so applications can stay running through an update. I suppose this is useful for some component vendors and strongly signed assemblies in corporate environments. But seriously, if you are going to throw .NET 4.5 into the mix, who won’t be recompiling all code and thoroughly test that code to work on .NET 4.5? A recompile requirement doesn’t seem that serious in light of a major version upgrade. 

Resources

Posted in .NET  

The Voices of Reason


 

Steven Berkovitz
March 13, 2012

# re: .NET 4.5 is an in-place replacement for .NET 4.0

Try looking at the File Version (properties dialog), not the Assembly Version to see which version of the file it is..

@koty
March 13, 2012

# re: .NET 4.5 is an in-place replacement for .NET 4.0

thank you for your explanation. .NET 4.5 looks like .NET 4.0 sp1 isn't it ?

Staffan
March 14, 2012

# re: .NET 4.5 is an in-place replacement for .NET 4.0

I suppose they had the ambition to release a "3.0/3.5 release", but realized they wanted to add all those new Task-based API:s into existing assemblies, rather than adding lots of System.IO.Async assemblies which would hurt later on. With there being just additions (and bug fixes) an "upgrade install" probably made sense to Redmond. Not justifying, only speculating.

Lex Li
March 14, 2012

# re: .NET 4.5 is an in-place replacement for .NET 4.0

Consider the old story of .NET 3.5 SP1, where lots of new features were added, they should this time name it as .NET 4 SP, instead of 4.5.

Mike
March 14, 2012

# re: .NET 4.5 is an in-place replacement for .NET 4.0

Microsoft sucks at versioning, they just can't seem to wrap their heads around semver. Only Hanselman and Haacked seem to get it, which is reflected in NuGet and MVC. Recently the EF team got called out on it, and they seem to be in the process of getting their act together, recently it's simply been 4.2, 4.3 etc.

But .NET itself is a mess, let's hope they rebase at 5.0 and then get it right.

Vasu
March 14, 2012

# re: .NET 4.5 is an in-place replacement for .NET 4.0

Can you elaborate how the IIS version dialog looks? There is no .NET 4.5 option in there? That would be very confusing is'nt it.

mknopf
March 14, 2012

# re: .NET 4.5 is an in-place replacement for .NET 4.0

Thanks for the heads up, we host hundreds of apps across more than 100 servers so this could have been a real issue for our Sys Admins if they weren't aware that it replaces the 4.0 assemblies

Michael K. Campbell
March 14, 2012

# re: .NET 4.5 is an in-place replacement for .NET 4.0

Rick,

As always a great post.

While this WILL cause all sorts of goofy problems and headaches for developers, the REAL problem here (as I see it) is that it delivers a huge NEGATIVE blow to the .NET Framework for the IT Pros and businesses (pointy-haired bosses) who will end up colliding with these 'stealth' versioning conflicts. They won't see this as an issue where Microsoft tried something new.

Instead, they'll see this as merely being a case where .NET apps are hard to support. So the next time developers want to use .NET for internal apps in companies where this was already a question of whether or not .NET made sense or not will see ADDITIONAL push-back from the folks that manage these apps.

That, and it's NOT like people didn't complain about everything you've listed here prior to them launching this silliness upon the world.

I complained about it more than 5 months ago here - where I also outlined how I'm worried about how much of a NEGATIVE sentiment this will create among businesses and IT pros who get bitten by the issues that this WILL cause:
http://www.devproconnections.com/article/net-framework/net-framework-45-versioning-faces-problems-141160

--Mike