DLL hell was mostly from the COM days, where a COM dll had to be registered, and clients of it would look it up in the registry. It was a nightmare because the filesystem (*.dll, *.ocx) could be modified leaving obsolete entries in the registry. Apps would stop working, it was horrible.
You'd then get the scenario where a new app installs and registers a new version of the DLL, thus breaking apps that really wanted the old version. You'd reinstall the old app, and break the new one in the process.
With .NET, there's no need to register the DLLs (the GAC is a special case, and has provision to avoid the versioning issue described above), the loader just picks up assemblies by looking in the correct paths.