CLR today supports multiple versions of an assembly side by side, contrast to native loader.
In the native world, when you call LoadLibrary(“foo.dll”) multiple times, you will only get one copy of foo.dll loaded. In CLR, since the assembly name includes version number, you can issue Assembly.Load() on different versions of assembly foo, and multiple versions of assembly foo will be loaded. (Let’s ignore the binding policy here).
But assemblies side by side does not come for free.
The second one is the killer. You have to be very careful about expose types from the assembly, since any type could potentially be compared against a type from a different version of the same assembly, results in InvalidCastException.
Assemblies side by side works when none of the types are exposed by other assemblies, or consumers of the two versions of the assembly work independently, and never talk to each other.
Beyond those simple scenarios, it requires strict engineering and QA to make multiple versions of an assembly side by side work.
These restrictions make assemblies side by side much less useful than it sounds.