目次

概要

ここでは、C# の言語バージョンを明示的に指定する方法について説明します。

コンパイラー バージョンと言語バージョン

最新の C# の機能を使うためには、コンパイラー自体も最新のものを使う必要があります。 一方で、その逆は話が違って、新しいコンパイラーでもC# の「言語バージョン」をオプション指定することで、古い C# のまま維持することができます (指定方法は次節で説明)。

基本的に C# は破壊的変更を好まない(ほとんどないし、あっても影響が軽微なもののみ)言語なので、古いバージョンを維持するメリットはあまりありません。 しいて言うなら、諸事情あって最新のコンパイラーを使えない人との共同作業の際に、自分は新しいコンパイラーを使うけども言語バージョンだけは下げておきたいというときに使います。

特に指定がない場合、基本的には「最新の言語バージョン」になります。 ただ、後述しますが、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# コンパイラーのオプションで、言語バージョンを明示的に指定することができます。 特に何も指定しなかった場合、後述する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 などというように、小数点以下は省略可能です。

後者は、defaultlatestlatestMajorpreview の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 (オプション未指定)の時の挙動が latest と同じになりました。 代わりに、latestMajorpreview が追加されました。

C# 7.0 以降、マイナー リリースをするようになって、リリースのサイクルが短くなりました。 しかし、サイクルが短い分、バグの発生も多く、 C# 7.X の頃は「default 挙動を 7.0 で止める」という苦肉の策でしのいでいました。 それが、C# 8.0 からは preview オプションを指定できるように変更して、 早期リリースと安定性の両立を図っています。

バグ修正

実のところ、古いバージョンを明示しても、完全に昔の挙動になるとは限りません。 「バグ修正」という扱いのものは、バージョン指定によらず挙動が変わります。

例えば、以下のようなものがあります。

これらはそれぞれ、C# 7.1 世代、8.0 世代のコンパイラーから入ったものですが、 それ以降のコンパイラーを使った場合、たとえ LangVersion を明示的に 7.0 にしたとしてもコンパイルできます。

極々稀ではありますが、深刻なバグの場合には挙動を変えてでも直す(破壊的変更になる)こともあるのでご注意ください。

更新履歴

ブログ