NuGetパッケージのバージョン依存関係の解決ルール

## バージョン番号の基礎

### フォーマット

特定のバージョン番号のフォーマットは`Major.Minor.Patch [-Suffix]`の形式であり、以下の要素があります：

- Major：大きな変更
- Minor：後方互換性のある新機能
- Patch：後方互換性のあるエラー修正
- Suffix（オプション）：ハイフンに続く、Semantic Versioning or SemVer 1.0 conventionに従うプレリリースバージョンを示す文字列

```
1.0.1
6.11.1231
4.3.1-rc
2.2.44-beta1
```

### ワイルドカード

| 記法       | 適用ルール	    | 説明                                                   |
| --------- | ------------- | ----------------------------------------------------- |
| 1.0       | x ≥ 1.0       |  最小バージョン、包含                                      |
| (1.0,)    | x > 1.0       |  最小バージョン、排他                                      |
| [1.0]     | x == 1.0      |  正確なバージョン一致                                     |
| (,1.0]    | x ≤ 1.0       |  最大バージョン、包含                                      |
| (,1.0)    | x < 1.0       |  最大バージョン、排他                                      |
| [1.0,2.0] | 1.0 ≤ x ≤ 2.0 |  正確な範囲、包含                                        |
| (1.0,2.0) | 1.0 < x < 2.0 |  正確な範囲、排他                                        |
| [1.0,2.0) | 1.0 ≤ x < 2.0 |  混合包含最小値と排他的最大値バージョン                       |
| (1.0)     | 無効           |  無効                                                 |

🔔 最も一般的なのは1番目の記法です

```xml
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
```

### バージョン番号の正規化

- 先行ゼロを無視する

```
1.00 -> 1.0
1.01.1 -> 1.1.1
1.00.0.1 -> 1.0.0.1
```

- バージョン番号の4番目の部分が0の場合、無視する

```
1.0.0.0 -> 1.0.0
1.0.01.0 -> 1.0.1
```

- ビルドメタデータを無視する

```
1.0.7+r3456 -> 1.0.7
```


❗`pack`と`restore`操作は、可能な限りバージョンを標準化し、すでに構築されたパッケージに対して、この標準化はパッケージ自体のバージョンには影響しません。依存関係を解決する際にNuGetがバージョンをマッチングする方法にのみ影響します。


## 依存関係の解決ルール

パッケージの復元には、依存関係を解決するために4つの主要なルールがあります。

### ルール1：最低バージョン

- バージョン制約が`1.0.0`で、ソースには`1.0.0`と`1.0.0-pre`のバージョンが存在する場合、優先的に`1.0.0`を返します。

  ❗`1.0.0`は`1.0.0-pre`よりもバージョンが低いため、優先度が高く、`1.0.0`を返します。

- バージョン制約が`1.0.0`で、ソースには`1.0.0`と`0.0.9`のバージョンが存在する場合、優先的に`1.0.0`を返します。

- バージョン制約が`[1.0.0]`で、ソースに`1.0.0`のバージョンが存在しない場合、復元が失敗します。


### ルール2：フローティングバージョン

フローティング依存関係バージョンは、`*`文字で指定されます。 例えば、`6.0.*`とすると、このバージョン規則は「最新の`6.0.x`バージョンを使用する」という意味になります。`4.*`は「最新の`4.x`バージョンを使用する」という意味になります。フローティングバージョンを使用すると、プロジェクトファイルの変更を最小限に抑えながら、依存関係の最新バージョンを維持することができます。

```xml
<PackageReference Include="Newtonsoft.Json" Version="12.0.*" />
```


### ルール3: 最近のバージョンを優先する

アプリケーションのパッケージグラフに同じパッケージの異なるバージョンが含まれている場合、NuGet はグラフ内のアプリケーションに最も近いパッケージを選択し、他のすべてのパッケージを無視します。この動作により、アプリケーションは依存関係グラフ内の特定のパッケージバージョン ( package version ) を上書きできます。

ある`Application`は、`PackageB`と`PackageA`の`Version2.0`に依存していますが、`PackageA`は、`Version1.0`の`PackageB`に依存しています。したがって、「フラット化された依存関係」で`Version2.0`の`PackageB`が選択されます。

- Application

```xml
<PackageReference Include="PackageB" Version="2.0.0" />
<PackageReference Include="PackageA" Version="1.0.0" />
```

- PackageA(1.0.0)


```xml
<PackageReference Include="PackageB" Version="1.0.0" />
```

### ルール4: 「いとこ依存関係」

NuGet は、アプリケーションから同じ距離にあるグラフで異なるパッケージバージョンを参照する場合、すべてのバージョン要件を満たす最低バージョンを使用します。

🔔 簡単に言えば、最低適用バージョンルールを依存関係ツリー全体に適用することです。

- Application

```xml
<PackageReference Include="PackageA" Version="1.0.0" />
<PackageReference Include="PackageC" Version="2.0.0" />
```

- PackageA

```xml
<PackageReference Include="PackageB" Version="1.0.0" />
```

- PackageC

```xml
<PackageReference Include="PackageB" Version="2.0.0" />
```

## おわりに

このように、NuGetパッケージのバージョン依存関係の解決には、上記の4つのルールがあります。これらのルールにより、NuGetは、プロジェクトに必要な最新バージョンのパッケージを自動的に取得し、依存関係を解決することができます。