Visual Studio と C#、および、フレームワーク（プラットフォーム）の関係

## はじめに

投稿記事サンプルコードは、Visual Studio Community 2022 を利用して、.NET 8 と .NET Framework 4.8 で確認しています。
Visual Studio 2022（17.12）としては、C# 13.0 をサポートしていますが、.NET Framework 4.8 は C# 7.3 が既定となっているため、サンプルコードは C# 7.3 機能範囲で記述しています。

上記のような関係があるので、Visual Studio と C#、および、フレームワーク（プラットフォーム）の関係についてまとめてみたいと思います。

::: note
「フレームワーク（プラットフォーム）」という記載をしていますが、以降は「フレームワーク」という記載にさせて頂きます。
:::

::: note
フレームワーク、プラットフォームなどを Copilot に確認してみました。 

- フレームワークは、アプリケーション開発を容易にするために提供される再利用可能なライブラリとツールのセットです。
- プラットフォームは、ソフトウェアが動作するための基盤や環境を提供します。ハードウェア、オペレーティングシステム、ランタイム環境などを含む広範な概念です。

.NET は、プラットフォームであり、また、フレームワークでもあります。
.NET Framework は、主にフレームワークとして分類されますが、プラットフォームの要素も持っています。
:::


## ライフサイクル
### Visual Studio

| 製品名               | 最終アップデート           | 開始日     | 延長サポート終了日 |
| ------------------- | ------------------------ | ---------- | ---------------- |
| Visual Studio 2022  | －                       | 2021-11-08 | 2032-01-13       |
| Visual Studio 2019  | 16.11                    | 2019-04-02 | 2029-04-10       |
| Visual Studio 2017  | 15.9                     | 2017-03-07 | 2027-04-13       |
| Visual Studio 2015  | Update 3（14.0.25431.01） | 2015-07-20 | 2025-10-14       |
| Visual Studio 2013  | Update 5（12.0.40629.00） | 2014-01-15 | 2024-04-09       |
| Visual Studio 2012  | Update 5（11.0.61030.00） | 2012-10-31 | 2023-01-10       |

::: note
[製品およびサービスのライフサイクル情報の検索 - Microsoft Lifecycle | Microsoft Learn](https://learn.microsoft.com/ja-jp/lifecycle/products/) 情報と同様に、開始日は初期リリース日、延長サポート終了日は最終アップデートの延長サポート終了日としています。
:::

### フレームワーク

フレームワークのライフサイクルは、[.NET Framework と .NET](https://qiita.com/chai0917/items/d939fa7aacff5f27e0ed) に記載しているので、こちらをご確認ください。

## Visual Studio と C# の関係

### C# バージョンと新機能
> [C Sharp (programming language) - Wikipedia](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)#Versions)
> [C# の歴史 | Microsoft Learn](https://learn.microsoft.com/ja-jp/dotnet/csharp/whats-new/csharp-version-history)
> [C# によるプログラミング入門 | ++C++; // 未確認飛行 C](https://ufcpp.net/study/csharp/)
> [【C#】バージョン間の隠れた機能変更と互換性の罠](https://qiita.com/Sakai_path/items/02fc286b4b5972217621)


| Visual Studio              | C#   | C# 新機能（抜粋）                                  |
| -------------------------- | :--: | ------------------------------------------------- | 
| Visual Studio 2022 17.12   | 13.0 | params コレクション、 Lock クラスに対する lock       |
| Visual Studio 2022 17.8    | 12.0 | プライマリ コンストラクタ、コレクション式、InlineArray |
| Visual Studio 2022 17.4    | 11.0 | 生文字列リテラル、required メンバー、リスト パターン   |
| Visual Studio 2022 17.0    | 10.0 | record struct、global using、ファイルスコープ名前空間 |
| Visual Studio 2019 16.8    | 9.0  | レコード型、init-only プロパティ、トップレベルステートメント |
| Visual Studio 2019 16.3    | 8.0  | null 許容参照型、null 合体代入、switch 式、範囲アクセス |
| Visual Studio 2017 15.7    | 7.3  | タプルの ==, != 比較、ref 再代入、stackalloc 初期化子  |
| Visual Studio 2017 15.5    | 7.2  | 先頭区切り文字、private protected、readonly struct   |
| Visual Studio 2017 15.3    | 7.1  | 非同期 Main、default 式、タプル要素名の推論           |
| Visual Studio 2017 15.0    | 7.0  | タプル、型スイッチ、ローカル関数、throw 式             |
| Visual Studio 2015         | 6.0  | null 条件演算子、nameof 演算子、文字列補間、using static |
| Visual Studio 2012 / 2013  | 5.0  | async/await                                   |

## Visual Studio と フレームワークの関係

Visual Studio プロジェクトで、ターゲットとして指定可能なフレームワークを記載します。

### .NET

| Visual Studio            | .NET                    |
| -------------------------| ----------------------- |
| Visual Studio 2022 17.12 | 5.0、6.0、7.0、8.0、9.0 |
| Visual Studio 2022 17.7  | 5.0、6.0、7.0、8.0      |
| Visual Studio 2022 17.2  | 5.0、6.0、7.0           |
| Visual Studio 2022 17.0  | 5.0、6.0                |
| Visual Studio 2019 16.8  | 5.0                     |


### .NET Framework

| Visual Studio            | .NET Framework                              |
| -------------------------| ------------------------------------------- |
| Visual Studio 2022 17.0  | 4.6.2 以降                                   |
| Visual Studio 2019 16.0  | 3.5（2.0, 2.5 内包）、4.0、4.5、4.6、4.7、4.8 |
| Visual Studio 2017 15.9  | 3.5（2.0, 2.5 内包）、4.0、4.5、4.6、4.7、4.8 |
| Visual Studio 2017 15.0  | 3.5（2.0, 2.5 内包）、4.0、4.5、4.6、4.7      |
| Visual Studio 2015       | 3.5（2.0, 2.5 内包）、4.0、4.5、4.6          |
| Visual Studio 2013       | 3.5（2.0, 2.5 内包）、4.0、4.5               |
| Visual Studio 2012       | 3.5（2.0, 2.5 内包）、4.0、4.5               |

::: note
Visual Studio 2012 - 2019 について、3.5 SP1、4.5.2、4.6.2、4.7.2、4.8.1 という詳細バージョン記載は割愛しています。
:::


## フレームワークと C# の関係

### フレームワークの C# 既定バージョン

> [言語のバージョン管理 - C# reference | Microsoft Learn](https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/language-versioning#defaults)

Visual Studio プロジェクト生成時、対象フレームワークによって、下記、C# 既定バージョンが選択されます。

| フレームワーク     | C# 既定バージョン  |
| ----------------- | ----------------- |
| .NET 9.x          | C# 13             |
| .NET 8.x          | C# 12             |
| .NET 7.x          | C# 11             |
| .NET 6.x          | C# 10             |
| .NET 5.x          | C# 9.0            |
| .NET Core 3.x     | C# 8.0            |
| .NET Core 2.x     | C# 7.3            |
| .NET Standard 2.1 | C# 8.0            |
| .NET Standard 2.0 | C# 7.3            |
| .NET Standard 1.x | C# 7.3            |
| .NET Framework 全て | C# 7.3           |

::: note
上記表は Visual Studio 2022 の場合です。
Visual Sutdio でサポートしている C# のバージョンが、上記表よりも低い場合は、Visual Studio サポート範囲の C# バージョンとなります。
:::


### C# バージョン設定
> [言語バージョンの構成 - C# reference | Microsoft Learn](https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/configure-language-version)

Visual Studio IDE からは C# バージョン設定はできませんが、プロジェクトファイルをテキストエディタで編集することで、C# バージョンを指定することが可能です。

```XML
<PropertyGroup>
   <LangVersion>13.0</LangVersion>
</PropertyGroup>
```

### .NET

> https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/language-versioning
> C# 13 は、.NET 9 以降のバージョンでのみサポートされています。 C# 12 は、.NET 8 以降のバージョンでのみサポートされています。 C# 11 は、.NET 7 以降のバージョンでのみサポートされています。

C# 新機能にあわせて、.NET 機能強化も実施しているため、上記を前提としています。
.NET 機能強化に依存しない機能であれば、「C# バージョン設定」手順を利用することで利用可能となります。

具体例として、「C# 11 新機能 - UTF-8 リテラル」で確認してみます。
.NET 6.0 - C# 10 の環境で、下記コードを、ビルドしてみます。

```CSharp
ReadOnlySpan<byte> span = "Hoge"u8;  // UTF-8 リテラル
var sb = new StringBuilder();
foreach (var c in span)
{
  sb.Append(string.Format("0x{0:X2} ", c));
}
textBox1.Text = sb.ToString().TrimEnd();
```
```
機能 'UTF-8 文字列リテラル' は C# 10.0 では使用できません。言語バージョン 11.0 以上を使用してください。
```

「C# バージョン設定」手順で C# 11 に変更すると、ビルドでき、実行も問題ありません。

::: note
.NET 機能強化が連動して実施されている機能についても、追加された型などを用意するなどの対策はあるようです。
:::


### .NET Framework 

「C# バージョン設定」手順で C# バージョンを設定できますが、.NET に依存する機能については、.NET Framework では同等には利用できないケースがあります。

::: note
UTF-8 リテラルについては、下記理由で例として適切ではなく
- ReadOnlySpan<T>は公式にSystem.Memoryパッケージとしてnuget経由で提供されています。
- 有志による互換性のリストではpolyfillすら要らずに対応可能扱いです
  - https://gitlab.com/-/snippets/2367119
  - https://sergeyteplyakov.github.io/Blog/c%23/2024/03/06/CSharp_Language_Features_vs_Target_Frameworks.html

C#11のGeneric Mathや、C#8のデフォルトinterfaceメソッドなどの方が、例としては適切とのご指摘を受けて、以下を修正しました。
:::

~~例えば、「C# 11 新機能 - UTF-8 リテラル」は、`ReadOnlySpan<byte>` オブジェクトを利用しますが、.NET Framework では、`ReadOnlySpan<T>` 自体がサポートされていません。~~
例えば、「C# 11 新機能 - Generic Math」は、「C# バージョン設定」手順で C# 11 に変更しても、.NET Framework では利用できません。

```CSharp
static T Sum<T>(IEnumerable<T> items) where T : INumber<T>
{
  var sum = T.Zero;
  foreach (var x in items) sum += x;
  return sum;
}
```
```CSharp
int sum = Sum(new int[] { 1, 2, 3, 4, 5 });
```

- ビルドエラー内容
  - 'T' で非 virtual メンバー参照を実行できません。これは型パラメーターであるためです
  - 型 'int' はジェネリック型またはメソッド 'Form1.Sum<T>(IEnumerable<T>)' 内で型パラメーター 'T' として使用できません。'int' から 'INumber<int>' へのボックス変換がありません
  - 型または名前空間の名前 'INumber<>' が見つかりませんでした (using ディレクティブまたはアセンブリ参照が指定されていることを確認してください)