.NET 4.0 has a new GAC, why? – Dev

The best answers to the question “.NET 4.0 has a new GAC, why?” in the category Dev.


%windir%\Microsoft.NET\assembly\ is the new GAC. Does it mean now we have to manage two GACs, one for .NET 2.0-3.5 applications and the other for .NET 4.0 applications?

The question is, why?


I also wanted to know why 2 GAC and found the following explanation by Mark Miller in the comments section of .NET 4.0 has 2 Global Assembly Cache (GAC):

Mark Miller said…
June 28, 2010 12:13 PM

Thanks for
the post. “Interference issues” was
intentionally vague. At the time of
writing, the issues were still being
investigated, but it was clear there
were several broken scenarios.

For instance, some applications use
Assemby.LoadWithPartialName to load
the highest version of an assembly. If
the highest version was compiled with
v4, then a v2 (3.0 or 3.5) app could
not load it, and the app would crash,
even if there were a version that
would have worked. Originally, we
partitioned the GAC under it’s
original location, but that caused
some problems with windows upgrade
scenarios. Both of these involved code
that had already shipped, so we moved
our (version-partitioned GAC to
another place.

This shouldn’t have any impact to most
applications, and doesn’t add any
maintenance burden. Both locations
should only be accessed or modified
using the native GAC APIs, which deal
with the partitioning as expected. The
places where this does surface are
through APIs that expose the paths of
the GAC such as GetCachePath, or
examining the path of mscorlib loaded
into managed code.

It’s worth noting that we modified GAC
locations when we released v2 as well
when we introduced architecture as
part of the assembly identity. Those
added GAC_MSIL, GAC_32, and GAC_64,
although all still under
%windir%\assembly. Unfortunately, that
wasn’t an option for this release.

Hope it helps future readers.


Yes since there are 2 distinct Global Assembly Cache (GAC), you will have to manage each of them individually.

In .NET Framework 4.0, the GAC went through a few changes. The GAC was split into two, one for each CLR.

The CLR version used for both .NET Framework 2.0 and .NET Framework 3.5 is CLR 2.0. There was no need in the previous two framework releases to split GAC. The problem of breaking older applications in Net Framework 4.0.

To avoid issues between CLR 2.0 and CLR 4.0 , the GAC is now split into private GAC’s for each runtime.The main change is that CLR v2.0 applications now cannot see CLR v4.0 assemblies in the GAC.



It seems to be because there was a CLR change in .NET 4.0 but not in 2.0 to 3.5. The same thing happened with 1.1 to 2.0 CLR. It seems that the GAC has the ability to store different versions of assemblies as long as they are from the same CLR. They do not want to break old applications.

See the following information in MSDN about the GAC changes in 4.0.

For example, if both .NET 1.1 and .NET 2.0 shared the same GAC, then a .NET 1.1 application, loading an assembly from this shared GAC, could get .NET 2.0 assemblies, thereby breaking the .NET 1.1 application

The CLR version used for both .NET
Framework 2.0 and .NET Framework 3.5
is CLR 2.0. As a result of this, there
was no need in the previous two
framework releases to split the GAC.
The problem of breaking older (in this
case, .NET 2.0) applications
resurfaces in Net Framework 4.0 at
which point CLR 4.0 released. Hence,
to avoid interference issues between
CLR 2.0 and CLR 4.0, the GAC is now
split into private GACs for each

As the CLR is updated in future versions you can expect the same thing. If only the language changes then you can use the same GAC.


It doesn’t make a lot of sense, the original GAC was already quite capable of storing different versions of assemblies. And there’s little reason to assume a program will ever accidentally reference the wrong assembly, all the .NET 4 assemblies got the [AssemblyVersion] bumped up to The new in-process side-by-side feature should not change this.

My guess: there were already too many .NET projects out there that broke the “never reference anything in the GAC directly” rule. I’ve seen it done on this site several times.

Only one way to avoid breaking those projects: move the GAC. Back-compat is sacred at Microsoft.