C#10.0のコードがVisual Studio 2022でビルドできない場合はMicrosoft.Net.Compilers.Toolsetのせい

# 言語バージョンを更新したらビルドできない！
VS2019で作成したソリューションのプロジェクトはデフォルトで以下の設定になります。

* ターゲットフレームワーク：`net5.0`
* 言語：C# 9.0(`latest`)

VS2019で作成したソリューションとプロジェクトは、`.sln`ファイルや`.csproj`ファイルの中身の構造がVS2022では変更されませんでしたのでVS2022でそのまま開くことが可能です。
しかし、この状態でうきうきでC#10.0の`global using`や`file scoped namespace`に書き換えを行っても、**「`{`が必要です」といった基本的な文法エラーで殴られてビルドが通らない**ことがあります。アイエエエ！？CS1513！？CS1513ナンデ！？
(以下、うきうきで変更したら怒られたときの画面)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017924/bc820993-bc7e-643c-ece6-c7d057d1ed72.png)
上図をよく見たらわかるのですが、実は**VS2022のエディタはエラーだと思っていない**（問題は見つかりませんでしたとか言ってる）のに**ビルド時にエラー**になってます。
ついでにCS8032で「`アナライザー System.Text.Json.SourceGeneration.JsonSourceGenerator のインスタンスは C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\6.0.1\analyzers\dotnet\cs\System.Text.Json.SourceGeneration.dll (ファイルまたはアセンブリ 'Microsoft.CodeAnalysis, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'、またはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見つかりません。`) から作成できません。」とか言われて警告ビンタされます。
本稿ではこれの原因と対処法について説明します。

# 原因はSourceGeneratorとかに使う`Microsoft.Net.Compilers.Toolset`
結論からいうと`Microsoft.Net.Compilers.Toolset`を参照しているプロジェクトはこのライブラリのバージョンを更新しないとビルドが通りません。

https://www.nuget.org/packages/Microsoft.Net.Compilers.Toolset

こいつの説明に答えが書いてあります。

> .NET Compilers Toolset Package.
Referencing **this package will cause the project to be built using the C# and Visual Basic compilers contained in the package**, as opposed to the version installed with MSBuild.

以下、google翻訳
> .NETコンパイラツールセットパッケージ。
このパッケージを参照すると、MSBuildでインストールされたバージョンではなく、**パッケージに含まれているC＃およびVisualBasicコンパイラを使用してプロジェクトがビルドされます**。

**そんな仕様だったの！？**という感じではありますが、`.csproj`ファイルで設定したターゲットフレームワークや`LangVersion`よりも優先して`Microsoft.Net.Compilers.Toolset`に内蔵された`Roslyn`コンパイラが動作する、というわけです。`Roslyn`コンパイラのバージョンは`Microsoft.Net.Compilers.Toolset.dll`によって決まります。このため、**dllのバージョンが古いとC#10より前のコンパイラでビルドされるのでビルド時にエラーが出る**というわけです。エディタのエラー検出に使うコンパイラはおそらく`.csproj`の設定に依存して決まるのでしょう。多分。

# dllのバージョンと`Roslyn`コンパイラのバージョンの対応
MSDNに対応表があります。2022/01/14時点では3.xまでしか表がありません（英語サイトも）が、そのうち追加されるでしょう。

https://docs.microsoft.com/ja-jp/visualstudio/extensibility/roslyn-version-support?view=vs-2022

|Roslyn パッケージ バージョン| サポートされている Visual Studio の最小バージョン|
|:-|:-|
|3.x | Visual Studio 2019 |
|2.10.0| Visual Studio 2017 バージョン 15.9 |
|2.9.0| Visual Studio 2017 バージョン 15.8 |
|2.8.2| Visual Studio 2017 バージョン 15.7 |
|2.7.0| Visual Studio 2017 バージョン 15.6 |
|2.6.1| Visual Studio 2017 バージョン 15.5 |
|2.4.0| Visual Studio 2017 バージョン 15.4 |
|2.3.2| Visual Studio 2017 バージョン 15.3 |
|2.2.0| Visual Studio 2017 バージョン 15.2 |
|2.1.0| Visual Studio 2017 バージョン 15.1 |
|2.0.0| Visual Studio 2017 RTM |
|1.3.2| Visual Studio 2015 更新プログラム 3 |
|1.2.2| Visual Studio 2015 更新プログラム 2 |
|1.1.1| Visual Studio 2015 更新プログラム 1 |
|1.0.1| Visual Studio 2015 RTM |

私のプロジェクトでは3.11.0を使っていました。そりゃビルドが通らんわ・・・というわけでUpdate-Packageを実行すればビルドが通ったのでした。
なお、記事作成時点では最新バージョンは4.0.1になります。

# あとがき
初めてC#を触ったときから「`namespace`なんて99%はファイル全体で同じなのになんでインデントせにゃいかんの？」と思っていたのが、C#10.0でようやく解消できます。ずいぶん待たされましたし、`file scoped namespace`が導入される理由が「HelloWorldの簡略化」みたいなとこがありますが、これが嫌だったのは私だけだったんでしょうか？

他にもC#10やNET6にはたくさんの機能追加があります。特にLINQの`MaxBy,MinBy`は待望の機能ではないでしょうか？みなさんもぜひ最新バージョンへのアップデートを行いましょう！

https://qiita.com/hez2010/items/6771f600bb3459e738a2

https://qiita.com/RyotaMurohoshi/items/14efd4492ac14ee635cd