概要
ここでは、C# の言語バージョンを明示的に指定する方法について説明します。
コンパイラー バージョンと言語バージョン
最新の C# の機能を使うためには、コンパイラー自体も最新のものを使う必要があります。 一方で、その逆は話が違って、新しいコンパイラーでもC# の「言語バージョン」をオプション指定することで、古い C# のまま維持することができます (指定方法は次節で説明)。
基本的に C# は破壊的変更を好まない(ほとんどないし、あっても影響が軽微なもののみ)言語なので、古いバージョンを維持するメリットはあまりありません。 しいて言うなら、諸事情あって最新のコンパイラーを使えない人との共同作業の際に、自分は新しいコンパイラーを使うけども言語バージョンだけは下げておきたいというときに使います。
特に指定がない場合、基本的には「ターゲット フレームワークで指定した .NET Framework/.NET Core と同世代のバージョン」になります
(ターゲット フレームワークについては後述)。
ただ、後述しますが、C# 7.X 時代には一時的に「未指定では最新にならない」ときがありました。また、C# 8.0 からは、プレビュー版を早期に試せるように preview
オプション指定ができるようになりました。
C# コンパイラー
C# コンパイラーは、昔であれば .NET Framework を、今であれば .NET Core SDK をインストールすると付属してきます。 これらはいずれも.NET 公式サイトのダウンロード ページから入手できます。 基本的には、最新の SDK には最新のリリース版 C# コンパイラーが付属しています。
C# コンパイラーは現在はオープンソースになっていて、github からソースコードや、デイリー ビルド版のコンパイラーを入手することもできます。リポジトリ名は roslynです。
Roslyn という名前はコードネームがそのままリポジトリ名に残ったもので、 アメリカのワシントン州にある小さな町の名前が由来です。 (マイクロソフトは本社のあるレドモンド周辺の地名をよくコードネームにしていました。 最初に付けた名前がそのままオープンになってしまう現在はあまりそういう習慣もなくなりましたが、Roslyn プロジェクト発足時はまだそういう文化でした。)
現在の「Roslyn」実装になったのは C# 6.0 からで、その際にコンパイラー(csc コマンド)のバージョンが一度リセットされています。 なので、csc のバージョンは、C# のバージョンから5引いたくらいの数字になっています。 例えば、C# 7.0 に対応する csc のバージョンは 2.0 です。 ただし、csc は C# よりも細かく修正が掛かっている(主にバグ修正)ので、「5引けばバージョンが完全に一致」とはなりません。例えば C# 7.3 に対応する csc のバージョンは 2.7~2.11 です。
ターゲット フレームワーク
C# は .NET 上で動く言語です。 なので、C# で書いたプログラムをどういう環境で動かすか(どのバージョンの .NET がインストールされているか)も重要になります。
C#の言語バージョンと.NET バージョンで説明していますが、 C# の言語機能のいくつかはライブラリに依存しています。 そういう言語機能は基本的に、標準ライブラリに所望のクラスがあるバージョンより新しい .NET でしか使えなくなります。 (ただし、単にライブラリ依存な機能なら、クラスを自作・移植してくれば古いバージョンの .NET 上でも動かすことはできます。)
また、さらにレアですが、一部の機能は .NET 実行環境の特別なサポートが必要で、 どうやっても古い .NET では動かせないものもあります。 例えば以下のようなものがあります。
- ジェネリクス は .NET Framework 2.0 以降が必須
- インターフェイスのデフォルト実装 は .NET Core 3.0 以降が必須
そもそも言語機能に限らず、標準ライブラリとして何が使えるかによってプログラムの書き方は全然変わってきますし、 「どの .NET で動かしたいか」の指定は欠かせません。 これをターゲット フレームワーク(target framework)と言います。
ターゲットフレームワークにはモニカー(moniker: あだ名)と呼ばれる短縮名みたいなものが振られていて、 例えば以下のように書きます。
.NET のバージョン | モニカー |
---|---|
.NET Framework 4.8 | net48 |
.NET Core 3.0 | netcoreapp3.0 |
詳しくは公式ドキュメントである以下のページを参照してください。
言語バージョンの指定方法
C# コンパイラーのオプションで、言語バージョンを明示的に指定することができます。
特に何も指定しなかった場合、後述するdefault
に当たる挙動をします。
言語バージョンは、Visual Studio 上で行う場合、プロジェクトのプロパティを開いて、以下の場所から設定できます。
プロジェクト ファイル(拡張子が csproj
のファイル)を直接書き換える場合、PropertyGroup
の下にLangVersion
タグを書きます(タグ内に書けるオプションの種類は後述します)。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp2.2</TargetFrameworks>
<LangVersion>latest</LangVersion>
</PropertyGroup>
</Project>
また、C# コンパイラー(csc
)を直接使う場合には、-langversion
オプションを指定します
(書けるオプションは上記の LangVersion
タグと同じ)。
csc -langversion:latest sample.cs
LangVersion
前述の、csproj
ファイル中の LangVersion
タグや、csc
コマンドの -langversion
オプションでは、以下の2通りのオプション指定ができます。
7.0
など、バージョン番号を直接指定latest
など、後述するいくつかの文字列
前者の番号指定では、メジャー バージョンであれば 7
などというように、小数点以下は省略可能です。
後者は、default
、latest
、latestMajor
、preview
の4種類があります(大文字・小文字は区別しません)。オプションを指定しなかった場合はdefault
扱いになります。
ただ、これらの挙動は Visual Studio 2019/C# 8.0 世代のコンパイラーかそれ以前かで異なります。
古い挙動
C# 7.0 以前のコンパイラーにはそもそも番号指定か default
しかなかったので、
実質的には 7.1 ~ 7.3 (Visual Studio 2017)までの挙動になります。
以下のような挙動でした。
default
: 最新のメジャー バージョンlatest
: マイナー バージョンを含む最新バージョン
要するに、特に何も指定しなければ C# 7.0 になりました。
新しい挙動
C# 8.0 世代(Visual Studio 2019)以降のコンパイラーでは以下のような挙動になります。
default
: ターゲット フレームワークに応じて自動選択(同世代の最新の安定バージョン)latest
: マイナー バージョンを含む最新の安定バージョンlatestMajor
: 最新のメジャー バージョン(プレビュー版を除く)preview
: プレビュー版を含む最新バージョン
要するに、default
(オプション未指定)の時の挙動がだいぶ変わって、
同時に latestMajor
と preview
が追加されました。
C# 7.0 以降、マイナー リリースをするようになって、リリースのサイクルが短くなりました。
しかし、サイクルが短い分、バグの発生も多く、
C# 7.X の頃は「default
挙動を 7.0 で止める」という苦肉の策でしのいでいました。
それが、C# 8.0 からは preview
オプションを指定できるように変更して、
早期リリースと安定性の両立を図っています。
また、C# 8.0 ではインターフェイスのデフォルト実装のように、
所定のバージョン以上でないと動かない機能も提供されるようになりました。
一応、インターフェイスのデフォルト実装のような一部の機能を除けば古い実行環境でも C# 8.0 の新機能を使えますが、
混乱の元なので推奨はされていません。
そのため、default
(オプション未指定)の挙動は「ターゲット フレームワークに応じて自動選択」になりました。
latest
を含め、言語バージョンの指定は「わかっている人向け」のオプションになります。
default
の際、どのターゲット フレームワークのときにどの言語バージョンになるかは以下のページで確認できます。
バグ修正
実のところ、古いバージョンを明示しても、完全に昔の挙動になるとは限りません。 「バグ修正」という扱いのものは、バージョン指定によらず挙動が変わります。
極々稀ではありますが、深刻なバグの場合には挙動を変えてでも直す(破壊的変更になる)こともあるのでご注意ください。 破壊的変更に関する情報は Roslyn リポジトリ中の docs/compilers/CSharp フォルダー以下にドキュメントがあります。 例えば、C# 7.3 から 8.0 での破壊的変更は以下のページに書かれています。