Prior to that, the system dirs were searched first, which was the trigger for the DLL hell issue.
But not even Microsoft's own products respected that in practice.
Also Aix uses the same model as Windows.
Finally, .NET Assemblies are versioned, and Microsoft has introduced Application Manifests around Windows XP.
https://docs.microsoft.com/en-us/windows/desktop/sbscs/appli...
So it a matter of actually taking the effort of specifying the versions that the application works with.
But then, you still have to put up with defining potentially hundreds of <bindingRedirect>s in config files to even get an application to run correctly, even though they mostly don't share their DLLs.
The only thing it takes is Nuget dowloading a newer version of some dependency another library depends on, even if it's backwards compatible with the old API. Which, of course, it should always be if you haven't switched to a new major version.
Edit: Also, I find it very disturbing that the resulting errors always happen to be crashes during runtime instead of up-front. If that happens with a plugin or through reflection: fine. But for most of .NET code, dependencies should be able to be loaded during startup.