You need to make a clear distinction between the CLR (i.e. the "runtime") and the framework libraries (i.e. the "framework"). You execute your code on or with the first, your code is compiled against and uses the later. Unfortunately when using the the term ".NET version" one is usually referring to the whole package of both runtime and framework, regardless of their individual versions which - as has been said - can differ.
You can detect the installed framework versions. That doesn't, however, tell you which one you are actually using at runtime.
I'm not sure about 4.5, but with 2.0 vs. 3.0 or 3.5 Environment.Version
was of no help since it always returned 2.0 as all those framework versions were using the CLR 2.0. I presume that with the framework 4.5 the CLR version is still 4.0, which would explain that Environment.Version
returns 4.0.x even in that case.
A technique that may work for you is to check for a type, method or property in the core libraries (mscorlib, System.Core, etc.) that you'd know only existed starting with a particular .NET framework version.
For example, the ReflectionContext class seems to be totally new with the .NET framework 4.5 and conveniently lives in mscorlib
. So you could do something like this.
public static bool IsNet45OrNewer()
{
// Class "ReflectionContext" exists from .NET 4.5 onwards.
return Type.GetType("System.Reflection.ReflectionContext", false) != null;
}
Having all that said, one could question why you need to know which .NET version you are using. Simply try to access the features you require and possibly gracefully fallback to something else (that was available in older versions) if they are not present.
Update: Note that the term .NET 4.5 refers to the whole package of several assemblies that make up the base class libraries (BCL) and more (collectively called "framework") plus the runtime itself, i.e. the CLR - both of which can have different versions, as has been said.
I don't work for Microsoft and have no insight into the real reasons behind the lack of a (single) function or API to get "the .NET framework version", but I can make an educated guess.
It is not clear what information in particular such a function/API should provide. Even the individual assemblies of the BCL don't share a common (assembly/file) version. For example, with .NET 3.0 and 3.5, the mscorlib.dll had version 2.0.x while only the new assemblies of WCF and WF had 3.0 something. I think even with .NET 3.5 the System.ServiceModel.dll
still had version 3.0.x. What I'm trying to say, there is no unified version on all assemblies of the framework. So what should an API call like, say, System.Environment.FrameworkVersion
return? What value would the version be (even if it did return the "symbolic" version like 4.5, it would be of little value, wouldn't it?).
Too specific Some new features might arrive in SPs to existing versions, plus being part of a new version. Doing feature checking, your application might run perfectly well on previous versions, that have been updated, while with explicit version checking it might unneccessarily restrict itself to the newest version. I don't have an example from the .NET world for this, but in general (and in Windows itself, e.g. WMI) it can and did happen.
Not wanted. I could imagine that a method to figure "the version of the framework" that is currently being used by an application is not even desirable for them to provide. There is a long and unholy history of version checking fallacies (see "Don't Check Version" paragraph for concepts that apply to .NET as well), in the native/Win32 world. For example, people used the GetVersion
and GetVersionEx
APIs wrong, by only checking that they run the version they knew was the newest when they wrote their application. So, when the application was run on a newer version of windows, it wouldn't run, even though the features they really were using are still there. Microsoft might have considered issues like that and thus not even provided some API in .NET.
Incidentally this is what Microsoft recommends in the remarks section of the GetVersion function:
Identifying the current operating system is usually not the best way
to determine whether a particular operating system feature is present.
This is because the operating system may have had new features added
in a redistributable DLL. Rather than using GetVersionEx to determine
the operating system platform or version number, test for the presence
of the feature itself.
The Windows Team Blog also has something to say about this.
I know all this was about Windows and native programming, but the concept and dangers are the same for .NET applications the framework and the CLR.
I would say feature checking with (graceful) fallback is thus a much more reliable and robust way to make sure your application is downwards compatible. If you only want your application to work with a specific version of .NET or newer, don't do anything special at all and count on the backwards compatibility of .NET itself.