First let me tell you that I like NuGet, it's awesome to get a decent package manager for .Net and the team has done a great job getting NuGet into its current state. That said there is still room for improvements and the way NuGet resolves dependencies is one of them.

The problem here is that NuGet by default finds the oldest version of package dependency that falls within the range you have specified. So if you have dependencies that follow SemVer, meaning that everything within the same major number is compatible, this would lead you to specify the following dependency  range:

<dependency id="ExamplePackage" version="[1.0.0, 2.0.0)" />

Meaning that everything within that range is ok for NuGet to use. In this scenario NuGet will by default look for the package with "the lowest minor version". While this is the "safest" approach I'm pretty sure it's not what the majority of users wants and expects. It also seems to contradict the nuget doco it self when it comes to versioning since it clearly states:

When most people install packages from NuGet, they want the latest “stable” release of that package

So if users would like the "latest stable release" it seems reasonable to assume that they would like the latest stable version of depending packages as well?

While this could be argued back and forth regarding Minor releases this rule also apply to patch versions. Ie if you depend on >= 4.5.0 and there is a 4.5.1 package available NuGet will pick 4.5.0. This to me seems completely wrong since you bump patch when you put out a hotfix for critical bugs. This means that users will get potentially buggy versions of their dependencies.

I'd argue that this is a bug in NuGet!

The workaround

While we wait for the NuGet team to fix this the workaround is to specify an explicit dependency strategy when installing packages:

install-package -DependencyVersion HighestMinor  {package name}

For a complete list of strategies please refer to the official doco.

You can take this one step further and make it the default strategy by putting the following in you machine wide nuget.config:

In closing

While I can see that the NuGet team want to take the safest approach and until SemVer has become the standard perhaps that's the right thing to do. My proposal would be to add an extra qualifier to the dependency to declare if the dependency is following SemVer or not. That could then cause NuGet to switch to the HighestMinor strategy which by definition is safe for SemVer compliant projects given that you specify a [{CurrentMajor}, {NextMajor}) which can be setup as the default if you use Ripple to generate your NuSpecs.

<dependency id="ExamplePackage" version="[1.0.0, 2.0.0)" strategy="SemVer" />

Perhaps that could be taken one step further by package publishers declaring in their package if they follow SemVer or not and that could be used by NuGet to select the most appropriate strategy.

Hope this helps!