はじめに
PcakgeReferenceとProjectReferenceを利用した下記のcsporjがあるとします。それぞれのプロジェクトをビルドする際に必要な.NET SDKのバージョンは何か分かるでしょうか?
<!-- パターン1.csproj --> <TargetFramework>net8.0</TargetFramework> ... <ProjectReference Include="../Hoge/Hoge.csproj" />
<!-- パターン2.csproj --> <TargetFramework>net8.0</TargetFramework> ... <PackageReference Include="Hoge" Version="1.0.0" />
<!-- パターン1とパターン2から参照されているプロジェクト --> <TargetFrameworks>net8.0;net9.0</TargetFrameworks>
答えはProjectReferenceの方はnet9で、PackageReferenceはnet8です。またややこしいことに、ビルドするのにnet9が必要でも実際にビルドされるtfmはnet8になります。
仕組みを理解すれば大したことではないのですが、割と初見殺しな気がするのでそこら辺について書き残しておきます。
概要
端的にまとめると
ProjectReferenceは依存先プロジェクトもビルドするためより新しいバージョンの.NET SDKを要求するPackageReferenceはビルド済みのライブラリを利用するため自身のプロジェクトをビルドできるSDKがあれば問題ない
という感じです。
PackageReference
PackageReferenceは既に特定のTargetFramework向けにビルド済みのアセンブリを利用します。(netstandard2.1など互換性のある下位のアセンブリを利用することもある)
ですのでビルドに必要となる.NET SDKは、あくまでビルドを実行するプロジェクト自身のTargetFrameworkに対応していればよいのです。
ProjectReference
ProjectReferenceはNuGetパッケージとは異なり、ソースコードレベルでの依存となります。ProjectReferenceを持つプロジェクトをビルドすると、依存先のプロジェクトも一緒にビルドされます。
つまりビルドに必要となる.NET SDKは、参照関係にあるすべてのプロジェクトのTargetFrameworkをサポートするバージョンが要求されます。global.jsonの影響がある可能性もあるかもですが、基本的に最新のものを入れておけばビルドできるはずです。
さいごに
私の場合ローカルでは色々なバージョンの.NET SDKが入っているので問題になることは少ないのですが、特にCI/CDで.NET SDKを用意する場合では気をつけたほうが良いでしょう。ProjectReferenceの場合は依存先も調べないといけないので、結構分かりづらくご注意ください。