C#(シーシャープ)は、マイクロソフトが開発した、汎用のマルチパラダイムプログラミング言語である。C#は、Javaに似た構文を持ち、C++に比べて扱いやすく、プログラムの記述量も少なくて済む。また、C#は、Windowsの.NET Framework上で動作することを前提として開発された言語であるが、2023年現在はクロスプラットフォームな.NETランタイム上で動作する。デスクトップ・モバイルを含むアプリケーション開発や、ASP.NETをはじめとするWebサービスの開発フレームワーク、ゲームエンジンのUnityでの採用事例などもある。

## 概要

開発にはボーランドのTurbo PascalやDelphiを開発したアンダース・ヘルスバーグを筆頭として多数のDelphi開発陣が参加している。
構文はC系言語(C言語、C++、Javaなど)の影響を受けており、その他の要素には、以前、ヘルスバーグが所属していたボーランド設計のDelphiの影響が見受けられる。また、主要言語へのasync/await構文や、ヘルスバーグが言語設計に関わるTypeScriptでのジェネリクス採用など、他言語への影響も見られる。

C#は共通言語基盤(共通言語ランタイムなど)が解釈する共通中間言語にコンパイルされて実行される。

また、C#はマルチパラダイムをサポートする汎用高レベルプログラミング言語で、静的型付け、タイプセーフ、スコープ、命令型、宣言型、関数型、汎用型、オブジェクト指向(クラスベース)、コンポーネント指向のプログラミング分野を含んでいる。他にも自動ボックス化、デリゲート、
プロパティ、インデクサ、カスタム属性、ポインタ演算操作、構造体(値型オブジェクト)、多次元配列、可変長引数、async/await構文、null安全などの機能を持つ。また、Javaと同様に大規模ライブラリ、プロセッサ・アーキテクチャに依存しない実行形態、ガベージコレクション、JITコンパイルによる実行の高速化、AOTコンパイラによる高速実行、などが実現されている(もっともこれらはC#の機能というより.NET によるものである)。

共通言語基盤 (CLI) といった周辺技術も含め、マイクロソフトのフレームワークである「.NET」の一部である。また、以前のVisual J++で「非互換なJava」をJavaに持ち込もうとしたマイクロソフトとは異なり、その多くの仕様を積極的に公開し、標準化機構に託して自由な利用を許すなど、同社の姿勢の変化があらわれている。

.NET構想における中心的な開発言語であり、XML WebサービスやASP.NETの記述にも使用される。他の.NET系の言語でも記述可能だが、.NET APIはC#からの利用を第一に想定されており、他の.NET系言語(特に2023年以降新構文の追加なしと宣言されたVB.NET)では利用できない、あるいは将来的に利用できなくなる機能が存在する。

マイクロソフトの統合開発環境(Microsoft Visual Studio)では、Microsoft Visual C#がC#に対応している。また、Visual Studio Codeに専用のC#向け拡張(C# DevKit)を導入することでクロスプラットフォームで開発することが可能。

共通言語仕様のCLSによって、他のCLS準拠の言語(F#やVisual Basic .NETやVisual C++ (C++/CLI) など)と相互に連携することができる。

## バージョンおよびリリース時期

| バージョン | 言語仕様 | | | リリース時期 | .NET | Visual Studio |
| --- | --- | --- | --- | --- | --- | --- |
| ECMA | ISO/IEC | マイクロソフト |
| 1.0 | ECMA-334:2003 (2002年12月) | ISO/IEC 23270:2003 (2003年4月) | 2002年1月 | 2002年1月 | .NET Framework 1.0 | .NET (2002) |
| - 1.1 - 1.2 | 2003年10月 | 2003年4月 | .NET Framework 1.1 | .NET 2003 |
| 2.0 | ECMA-334:2006 (2006年6月) | ISO/IEC 23270:2006 (2006年9月) | 2005年9月 | 2005年11月 | - .NET Framework 2.0 - .NET Framework 3.0 | 2005 |
| 3.0 | N/A | N/A | 2007年8月 | 2007年11月 | - .NET Framework 2.0 - .NET Framework 3.0 - .NET Framework 3.5 | 2008 |
| 4.0 | N/A | N/A | 2010年4月 | 2010年4月 | .NET Framework 4 | 2010 |
| 5.0 | ECMA-334:2017 (2017年12月) | ISO/IEC 23270:2018 (2018年12月) | 2013年6月 | 2012年8月 | .NET Framework 4.5 | - 2012 - 2013 |
| 6.0 | ECMA-334:2022 (2022年6月) | N/A | Draft | 2015年7月 | - .NET Framework 4.6 - .NET Core 1.0 - .NET Core 1.1 | 2015 |
| 7.0 | ECMA-334:2023 (2023年12月) | ISO/IEC 20619:2023  (2023年9月) | N/A | 2017年3月 | .NET Framework 4.7 | 2017 version 15.0 |
| 7.1 | N/A | N/A | N/A | 2017年8月 | .NET Core 2.0 | 2017 version 15.3 |
| 7.2 | N/A | N/A | N/A | 2017年11月 | .NET Core 2.0 | 2017 version 15.5 |
| 7.3 | N/A | N/A | N/A | 2018年5月 | - .NET Core 2.1 - .NET Core 2.2 - .NET Framework 4.8 | 2017 version 15.7 |
| 8.0 | N/A | N/A | N/A | 2019年9月 | - .NET Core 3.0 - .NET Core 3.1 | 2019 version 16.3 |
| 9.0 | N/A | N/A | N/A | 2020年11月 | .NET 5.0 | 2019 version 16.8 |
| 10.0 | N/A | N/A | Proposal | 2021年12月 | - .NET 6.0 - .NET 6.0.1 | 2022 version 17.0 |
| 11.0 | N/A | N/A | C# feature specifications | 2022年11月 | .NET 7.0 | 2022 version 17.4 |
| 12.0 | N/A | N/A | C# feature specifications | 2023年11月 | .NET 8.0 | 2022 version 17.8 |
| 13.0 | N/A | N/A | N/A | 2024年11月 | .NET 9.0 | 2022 version 17.12 |

## 言語仕様

さまざまな意味において、基盤であるCLIの機能をもっとも反映している言語であるといえる。C#にある組み込み型のほとんどは、CLIフレームワークに実装されている値型と対応している。

しかし、C#の言語仕様はコンパイラのコード生成については何も言及していないため、CLRに対応しなければならないとか、共通中間言語 (CIL) などの特定のフォーマットのコードを生成しなければならないとかいうことは述べられていない。

そのため、理論的にはC++やFORTRANのように環境依存のマシン語を生成することも可能である。しかし、現在存在するすべてのC#コンパイラはCLIをターゲットにしている。

.NET 7.0以降で可能になった事前コンパイルの一種である「Native AOT」でデプロイすることで実行可能な環境依存のバイナリを出力することが可能である。しかしながらこの手法もCLIとランタイムを事前に各アーキテクチャ向けのバイナリに変換しているだけであり、CLIを経由することに変わりはない。

特殊な例としては、UnityのScripting Backendである「IL2CPP」や「Burst」がある。
IL2CPPはC#をコンパイルしたCILをさらにC++コードへと変換後、ネイティブバイナリへC++コンパイラによってコンパイルされる。BurstはC#をコンパイルしたCILをLLVMコンパイラによってネイティブバイナリへコンパイルするものである。

### Hello World

最新のC#ではHello Worldを下記の通りに1行で記述できる。

上記のコードは、コンパイラによって下記の様なコードに展開される。

次の言語機能によって実現されている。ただし、未対応の古いコンパイラを用いる場合は、省略できない。

- 最上位レベルのステートメント
- 暗黙的な`using`

### CやC++からの改良点

C#では、CやC++と比較してさまざまな制限や改良が加えられている。また、仕様の多くはC#言語というよりは、基盤である .NET そのものに依拠している。Javaで導入された制限および改良をC#でも同様に採用しているものが多いが、C#で新たに導入された改良がのちにJavaにも同様に採用されたものもある。その例を次に挙げる。

#### 構文や構文以外の改良点

- 外のブロックで宣言した変数と同じ名前の変数を、内のブロックで再宣言してはいけない。再宣言は便利なこともあれば、混乱や曖昧のもとと主張されることもあるが、C#では禁止されている。
- C#にはブール型`bool`が存在し、`while`文や`if`文のように条件をとるステートメントには、`bool`型の式を与えなければならない。C言語では、ブール型が無く`int`型(0を偽とし、非0を真とする)に兼用させた上、(ヌルポインタを偽とみなすこととするといろいろと便利だった、ということもあり)ポインタでも`while`文や`if`文に与える式にできる、という仕様としていた。これは便利なこともあったが、本来比較式を記述すべきところで誤って代入式を記述してもコンパイル適合となってしまうなど、ミスが見逃されることもあった。C#ではミスを防止するために、そのような仕様ではなくブール型を独立させ、またブール型を厳密に要求する場所を多くしている。
- `switch`文に整数型あるいは整数型に準ずる型のみならず、文字列型`string`を使用できる。`case`ラベルには、整数型あるいは整数型に準ずる型の定数のみならず、文字列リテラル(文字列定数)を使用できる。
  - C# 7.0 以降では `case`ラベルに複雑なパターンマッチングを行うことが可能で複雑な判定を簡易な記述で記載が可能。
- 組み込み型のサイズおよび内部表現が仕様で定められており、プラットフォームや処理系に依存しない。浮動小数点数はIEEE 754に準拠する。文字および文字列はUTF-16エンコーディングを採用する。
  - C# 9.0以降では CPUによってサイズの異なる整数型 `nint/nuint`が追加された
  - C# 11.0 以降では文字列をUTF-8として扱う「UTF-8文字列リテラル」が追加された

#### ポインタとメモリ管理

- ポインタをサポートする。ポインタは`unsafe`スコープ内のみで使用することができ、適切な権限をもつプログラムのみが`unsafe`とマークされたコードを実行することができる。オブジェクトへのアクセスの大部分は管理された安全な参照によってなされ、大部分の算術演算はオーバフローのチェックがなされる。`unsafe`ポインタは値型や文字列を指すことができる。セーフコードでは、必ずしもそうする必要はないものの、`IntPtr`型を通してポインタをやりとりすることができる。
- マネージドなメモリを明示的に解放する方法は存在せず、参照されなくなったメモリはガベージコレクタによって自動的に解放される。ガベージコレクタは、メモリの解放忘れによって起こるメモリリークを解消する。C#は、データベース接続のようなアンマネージドなリソースに対しても明示的に制御する方法を提供している。これは`IDisposable`インタフェースと`using`ステートメントまたは`using`宣言によってなされる。

#### 名前空間とオブジェクト指向な型システム

- グローバル変数やグローバルメソッドは存在しない。すべてのフィールドとメソッドはクラスあるいは構造体の一部として宣言されなければならない。

- 名前空間は階層構造をもつ。つまり、名前空間は他の名前空間の中に宣言することができる。
- 組み込みの値型を含めたすべての型は、`object`クラス (`System.Object`) の派生型である。つまり`object`クラスのもつすべてのプロパティやメソッドを継承する。例えば、すべての型は`ToString()`メソッドをもつ。
- クラス (`class`) は参照型であり、構造体 (`struct`) および列挙型 (`enum`) は値型である。構造体はクラスよりも軽量で、C/C++との相互運用性に優れるが、派生型を定義することができない。
- クラスおよび構造体は複数のインタフェースを実装することができるが、多重継承はサポートされない。
- C#はC++に比べて型安全である。既定の暗黙変換は、整数の範囲を広げる変換や、派生クラスから基底クラスへの変換といった、安全な変換のみに限定される。これは、コンパイル時、JITコンパイル時、そして一部の動的なケースでは実行時に強制される。ブール型と整数型、列挙型と整数型、の間は暗黙変換はできない。暗黙変換をユーザー定義する際は、明示的にそのように指定しなければならない。これはC++のコンストラクタとは違った仕様である。
- C#は「Null安全」である。Null許容型、Null許容参照型を持ち、Null合体演算子などの構文・演算子を持つ。
- 列挙型のメンバーは、列挙型のスコープの中に置かれる。また、列挙型の定数名を取得することができる。さらに、列挙型の定数名から動的に定数値を得ることができる。
- アクセサの定義と利用を簡略化するためにプロパティ構文を利用できる。C++およびJavaにおけるカプセル化では、通例getter/setterアクセサとなるメンバー関数あるいはメソッドを定義して利用するが、C#ではプロパティ機能により、カプセル化を維持しつつ、あたかもフィールドを直接読み書きするような直感的な構文でオブジェクトの状態にアクセスすることができる。プロパティによってメンバーのアクセス制御やデータの正当性チェックを実行することができる。なお、イベントハンドラーに利用するデリゲートのカプセル化にはイベント構文 (`event`) が用意されている。
- ジェネリクス(総称型)の採用(C# 2.0以降)。C++のテンプレート、Javaのジェネリックスと異なりコンパイル後も型情報が保持される。また、Javaのジェネリクスと異なりプリミティブ型も型変数として使うことができる。

### C# 2.0からの仕様

#### 部分型

部分型 (Partial Type) が導入された。以下のようにクラスや構造体の宣言に`partial`修飾子をつけることで、その宣言を分割することができる。

これは以下と同義である:

これによって、巨大なクラスを分割したり、自動生成されたコードを分離したりすることができる。`partial` 修飾子はすべての宣言につける必要がある。

#### ジェネリクス

ジェネリクスが導入された。これは.NET Framework 2.0の機能である。クラス、構造体、インタフェース、デリゲート、メソッドに対して適用することができる。

.NETのGenericsはC++のテンプレート、あるいはJavaにおけるそれとも異なるもので、コンパイルによってではなく実行時にランタイムによって特殊化される。これによって異なる言語間の運用を可能にし、リフレクションによって型パラメーターに関する情報を取得することができる。また、`where`節によって型パラメーターに制約を与えることができる。一方、C++のように型パラメーターとして式を指定することはできない。なお、ジェネリックメソッドの呼び出し時に引数によって型パラメーターが推論できる場合、型パラメーターの指定は省略できる。

#### 静的クラス

静的クラスが導入された。`static`属性をクラスの宣言につけることで、クラスはインスタンス化できなくなり、静的なメンバーしか持つことができなくなる。

#### イテレータ

イテレータ#C# 2.0を参照。

##### yieldキーワード

`yield`キーワードによるコルーチンを使うことで、イテレータの生成を楽に実装できるようになった。

#### 匿名デリゲート

クロージャの機能を提供する匿名デリゲートが導入された。

#### プロパティに対する個別のアクセス制御

Property Accessors
プロパティの`get` もしくは `set`アクセサのどちらかにアクセス修飾子を指定することでアクセス制御が別個にできるようになった。次の例では、`get`アクセサは`public`、`set`アクセサは`private`である。

#### Null許容型とnull結合演算子

nullを保持できる値型、`Nullable`が導入された。

`int?`は`Nullable<int>`の糖衣構文である。また、nullを保持しているNull許容型のインスタンスをボックス化しようとすると、単に空参照 (null) に変換される。

また、null結合演算子 (`??`)が導入された。これは、`null`でない最初の値を返す。

この演算子は主に`Nullable`型を非`Nullable`型に代入するときに使われる。

#### その他

- 匿名メソッド
- External Aliases/Namespace Aliases Qualifiers
- プラグマディレクティブ/C言語の様な固定長の配列表記Fix Size Buffers

### C# 3.0からの仕様

#### varキーワード

`var` キーワードが導入され、型推論を利用したローカル変数の宣言ができるようになった。

#### 拡張メソッド

拡張メソッド (extension method) が導入された。既存のクラスを継承して新たなクラスを定義することなく、新たなインスタンスメソッドを疑似的に追加定義することができる。具体的には、入れ子になっていない、非ジェネリックの静的クラス内に、`this` 修飾子をつけた、拡張メソッドを追加する対象の型の引数を最初に持つメソッドをまず定義する。これによって、通常の静的メソッドとしての呼び出しの他に、指定した型のインスタンスメソッドとしての呼び出しを行うことができるメソッドを作ることができる。以下に例を挙げる:

この例は、文字列(`string` 型のインスタンス)を指定した回数繰り返し連結したものを返すメソッド `Repeat` を、既存の `string` 型に追加している。このメソッドは、以下のように呼び出すことができる:

また、列挙型やインタフェースなど本来メソッドの実装を持ち得ない型に、見かけ上インスタンスメソッドを追加することも可能である。以下に例を挙げる:

このメソッドは以下のように呼び出すことができる:

拡張メソッドは糖衣構文の一種であり、カプセル化の原則に違反するものではないが、必要な場合に限り注意して実装することがガイドラインとして推奨されている。

#### 部分メソッド

部分メソッドが導入された。部分型(`partial` 型)内で定義された `private` で、かつ戻り値が `void` のメソッドに `partial` 修飾子をつけることでメソッドの宣言と定義を分離させることができる。定義されていない部分メソッドは何も行わず、何らエラーを発生させることもない。例えば:

上のコードにおいて `Method()` を呼び出すと、Did something. と表示されるだけだが、ここで以下のコード:

を追加した上で `Method()` を呼び出すと、[DEBUG: Some message] Did something. と表示される。

#### ラムダ式

ラムダ式が導入された。この名前はラムダ計算に由来する。

以下の匿名メソッド

は、ラムダ式を使って次のように記述できる:

ラムダ式は匿名メソッドと同様に扱えるが、式形式のラムダが`Expression<TDelegate>`型として扱われた場合のみ匿名メソッドとして扱われず、コンパイラによって式木を構築するコードに変換される。匿名デリゲートが実行前にコンパイルされたCILを保持するのに対し、式木はCILに実行時コンパイル可能であるDOMのような式の木構造そのものを保持する。これはLINQクエリをSQLクエリなどに変換する際に役立つ。

以下は、3つの任意の名前の変数、整数、括弧、及び四則演算子のみで構成された式を逆ポーランド記法に変換する汎用的なコードである:

#### オブジェクト初期化の簡略化

オブジェクトの初期化が式として簡潔に記述できるようになった。

また、コレクションの初期化も同様に簡潔に記述できるようになった。

但し、上のコードでは匿名の変数に便宜的に \_\_p、\_\_l、\_\_d と命名している。実際はプログラマはこの変数にアクセスすることはできない。

#### 自動実装プロパティ

プロパティをより簡潔に記述するための自動実装プロパティが導入された。プロパティの定義に `get; set;` と記述することで、プロパティの値を保持するための匿名のフィールド(プログラマは直接参照することはできない)と、そのフィールドにアクセスするためのアクセサが暗黙に定義される。また、C# 5.0 までは `get;`と`set;`のどちらか片方だけを記述することは出来なかったが、C# 6.0 からは `get;` のみが可能。以下のコード:

は、以下のようなコードに相当する動作をする:

但し、上のコードでは匿名のフィールドに便宜的に `__value` と命名している。実際はプログラマはこのフィールドにアクセスすることはできない。

#### 匿名型

一時的に使用される型を簡単に定義するための匿名型が導入された。以下に例を挙げる:

上の式は、以下の内容のクラスを暗黙に定義する。定義されたクラスは匿名であるが故にプログラマは参照できない。

同じ型、同じ名前のプロパティを同じ順序で並べた匿名型は同じであることが保証されている。即ち、以下のコード:

において、`her.GetType() == him.GetType()` は `true` である。

#### 配列宣言の型省略

`new` キーワードを用いた配列の宣言の際、型を省略できるようになった。匿名型の配列を宣言する際に威力を発揮する。

#### クエリ式

LINQ をサポートするために、クエリ式が導入された。これは SQL の構文に類似しており、最終的に通常のメソッド呼び出しに変換されるものである。以下に例を示す:

上のコードは以下のように変換される:

C# 3.0で追加された構文の多くは式であるため、より巨大な式(当然クエリ式も含まれる)の一部として組み込むことができる。旧来複数の文に分けたり、作業用の変数を用意して記述していたコードを単独の式としてより簡潔に記述できる可能性がある。

出井秀行著の『実戦で役立つ C#プログラミングのイディオム/定石&パターン』(技術評論社、2017年)という書籍ではクエリ構文よりメソッド構文を推奨しており、クエリ構文ではLINQの全ての機能を使用できるわけではないこと、メソッド呼び出しは処理を連続して読める可読性があること、メソッド呼び出しであればMicrosoft Visual Studioの強力なインテリセンスが利用できることを理由に、著者はクエリ構文をほとんど使用していないと記している。

### C# 4.0からの仕様

#### dynamicキーワード

dynamicキーワードが導入され、動的型付け変数を定義できるようになった。dynamic型として宣言されたオブジェクトに対する操作のバインドは実行時まで遅延される。

#### オプション引数・名前付き引数

VBやC++に実装されているオプション引数・名前付き引数が、C#でも利用できるようになった。

#### ジェネリクスの共変性・反変性

ジェネリクスの型引数に対してin、out修飾子を指定することにより、ジェネリクスの共変性・反変性を指定できるようになった。

### C# 5.0からの仕様

- 非同期処理 (async/await)
- 呼び出し元情報属性
- foreach の仕様変更

### C# 6.0からの仕様

- 自動実装プロパティの初期化子
- get のみの自動実装プロパティおよびコンストラクタ代入
- 静的 using ディレクティブ
- インデックス初期化子
- catch/finally での await
- 例外フィルタ
- 式形式のメンバー (expression-bodied members)
- null条件演算子
- 文字列補間(テンプレート文字列)
- nameof 演算子
- #pragma
- コレクションの初期化子での拡張メソッド
- オーバーロード解決の改善

#### 静的 using ディレクティブ

静的 using ディレクティブを利用することで、型名の指定無しに他クラスの静的メンバーの呼び出しを行えるようになった。利用するには`using static`の後に完全修飾なクラス名を指定する。

#### 例外フィルタ

`catch`の後に`when`キーワードを使用することで、処理する例外を限定することができるようになった。

### C# 7.0からの仕様

- 出力変数宣言
- パターンマッチング (is 式/switch 文)
- タプル (タプル記法/分解/値の破棄)
- ローカル関数
- 数値リテラルの改善(桁セパレータ/バイナリリテラル)
- ref戻り値、ref変数
- 非同期戻り値型の汎用化
- Expression-bodied 機能の拡充(コンストラクタ/デストラクタ/get/set/add/remove)
- Throw 式

#### 出力変数宣言

`out`引数で値を受け取る場合、その場所で変数宣言可能となった。

#### パターンマッチング

##### is 式の拡張

`is`式の構文が拡張され、型の後ろに変数名を宣言できるようになった。
拡張された`is`式はマッチした場合に宣言した変数にキャストした値を代入し、さらにtrueと評価される。
マッチしなかった場合はfalseと評価され、宣言した変数は未初期化状態となる。

##### switch 文の拡張

`switch`文のマッチ方法が拡張され、`case`ラベルに従来の「定数パターン」に加え、新たに「型パターン」を指定できるようになった。
また、「型パターン」の`case`ラベルでは、`when`句に条件を指定することができる。
「型パターン」を含む`switch`文では、必ずしも条件が排他的でなくなったため、最初にマッチした`case`ラベルの処理が実行される。

#### タプル

タプルのための軽量な構文が導入された。従来の`System.Tuple`クラスとは別に、`System.ValueTuple`構造体が新しく追加された。

##### タプル記法

2個以上の要素を持つタプルのための記法が導入された。
引数リストと同様の形式で、タプルを記述できる。

##### 分解

多値戻り値を簡単に扱えるように、分解がサポートされた。

分解はタプルに限らない。`Deconstruct()`メソッドが定義されたクラスでも、分解を利用できる。

以下に、`DateTime`型に分解を導入する例を示す。

上記のコードで`DateTime`型に`Deconstruct()`拡張メソッドを定義し、

のように左辺で3つの変数に値を受け取ることができる。

#### 値の破棄

分解、out引数、パターンマッチングで、値の破棄を明示するために`_`が利用できるようになった。
破棄された値は、後で参照することはできない。

#### ref戻り値、ref変数

`ref`キーワードの使用方法が拡張された。これによって、安全な参照の使い道が広がった。

##### ref戻り値

戻り値の型を`ref`で修飾することで、オブジェクトの参照を戻り値とすることができる。

変数の寿命は変わらないため、メソッド終了時に破棄されるローカル変数をref戻り値とすることはできない。

##### ref変数

ローカル変数の型を`ref`で修飾することで、参照を代入することができる。

### C# 7.1からの仕様

#### 非同期なMainメソッド

Mainメソッドの戻り値として、`Task`型、`Task(int)`型が認められた。

#### default式

型推論可能な場面では、`default`の型指定は省略可能となった。

### C# 7.2からの仕様

C#7.2で追加された仕様は以下の通り。

#### 値型の参照セマンティクス

値型におけるパフォーマンス向上を意図した複数の機能が追加された。

##### in参照渡し、ref readonly参照戻り値

引数に`in`を指定することで、読み取り専用参照渡しを指定できる。
また、戻り値に`ref readonly`を指定することで、読み取り専用参照戻り値を指定できる。

これにより、構造体のコピーを避けると共に、意図しない値の変更を抑止できる。

##### readonly構造体

構造体宣言時に`readonly`を指定することで、真の読み取り専用構造体を定義できる。
readonly構造体の全てのフィールドは`readonly`でなければならず、`this`ポインタも読み取り専用となる。

これにより、メンバーアクセス時の意図しない防御的コピーを抑止できる。

##### ref構造体

構造体宣言時に`ref`を指定することで、ヒープ領域へのコピーを防ぐ構造体がサポートされる。
ref構造体では、box化できない、配列を作成できない、型引数になることができない、など、ヒープ領域へのコピーを防ぐための厳しい制限がかかる。

この機能は、`Span<T>`のような構造体をサポートするために利用され、unsafe文脈以外での`stackalloc`の利用をも可能とする。

#### 末尾以外の場所での名前付き引数

C#4.0で追加された名前付き引数が末尾以外でも利用できるようになった。

#### private protected アクセス修飾子

同一アセンブリ内、かつ、継承先からのアクセス許可を表す`private protected`アクセス修飾子が追加された。

#### 数値リテラルの改善

十六進リテラルの`0x`、二進リテラルの`0b`の直後のアンダースコアが認められた。

### C# 7.3からの仕様

C#7.3では以下の仕様が追加された。

- ジェネリック型制約の種類の追加
  - `System.Enum`, `System.Delegate`
  - `unmanaged` (文脈キーワード)

- `ref`ローカル変数の再割り当て
- `stackalloc`初期化子
- Indexing movable fixed buffers
- カスタム`fixed`ステートメント
- オーバーロード解決ルールの改善
- 出力変数宣言の利用箇所の追加

- タプル同士の比較

- バッキングフィールドに対するAttribute指定

### C# 8.0からの仕様

C# 8.0で追加された仕様は以下の通り。

#### null許容参照型

参照型にnull許容性を指定できるようになった。参照型の型名に`?`を付加した場合にnull許容参照型となる。

参照型の型名に`?`を付加しない場合、null非許容参照型となる。

フロー解析レベルでのnull許容性チェックが行われる。null許容値型の`Nullable<T>`のような新しい型は導入されない。

##### null許容コンテキスト

参照型のnull許容性は、null許容コンテキストによって有効、無効の切り替えが可能である。
C#7.3以前の互換性のために、既定では無効となっている。

- Nullable コンパイルオプション: プロジェクト全体でのnull許容コンテキストを指定する
- `#nullable` ディレクティブ: ソースコードの部分ごとにnull許容コンテキストを指定する
  - `annotations` オプション、`warnings`オプションにより、適用範囲を限定できる

##### null免除演算子

null許容参照型の変数名の後に `!`を使用することで、フロー解析時の警告が免除される。

#### インタフェースの既定メンバー

インタフェースのメンバーに既定の実装を指定できるようになった。また、インタフェースに静的メンバーを持つことができるようになった。

さらに、インタフェースのメンバーにアクセシビリティを指定できるようになった。

- 既定のアクセシビリティは、従来通り `public` となる。
- 実装があるインスタンスメンバーは、既定で `virtual` となり `override`可能である。
- 実装を`override`させないために`sealed`を指定することができる。

#### パターンマッチングの拡張

`switch`式が追加された。
プロパティパターン、タプルパターン、位置指定パターンの追加により、再帰的なパターンマッチングが可能になった。

- switch式
- 再帰パターン
  - プロパティパターン
  - タプルパターン
  - 位置指定パターン

#### 非同期ストリーム

`IAsyncEnumerable<T>`
インタフェースを返すことで、イテレータ構文と非同期構文の共存が可能になった。

`await foreach`によって非同期ストリームを列挙する。

#### 範囲指定

`Index`と`Range`を指定できる専用構文が追加された。

#### その他の仕様

- 静的ローカル関数
- null結合代入演算子
- 構造体の読み取り専用メンバー
- using 宣言
- ref構造体のDispose
- ジェネリクスを含むアンマネージ型
- 式中の`stackalloc`
- 文字列補間のトークン順序の緩和

### C# 9.0からの仕様

C# 9.0で追加された仕様は以下の通り。

- レコード
- プロパティのinitアクセサ
- 最上位レベルステートメント
- パターンマッチングの拡張
- new式の型推論
- 条件演算子の型推論
- 共変戻り値
- GetEnumeratorの拡張メソッド対応
- 静的匿名関数
- ラムダ式引数の破棄
- ローカル関数への属性適用
- パフォーマンスと相互運用
  - ネイティブサイズの整数型(`nint` `nuint`型)
  - 関数ポインタ(`delegate*`型)
  - 変数初期化フラグの抑制
- コードジェネレータのサポート
  - モジュール初期化子
  - 部分メソッドの拡張

### C# 10.0からの仕様

C# 10.0で追加された仕様は以下の通り。

- レコード構造体
- 構造体型の機能強化
- 補間された文字列ハンドラー
- global using ディレクティブ
- ファイル スコープの名前空間の宣言
- 拡張プロパティのパターン
- ラムダ式の機能強化
- const 補間文字列を許可する
- レコードの型で ToString() を封印できる
- 限定代入の機能強化
- 同じ分解で代入と宣言の両方を許可する
- メソッドで AsyncMethodBuilder 属性を許可する
- CallerArgumentExpression 属性
- 拡張 #line pragma
- 警告ウェーブ 6

### C# 11.0からの仕様

C# 11.0で追加された仕様は以下の通り。

#### 生文字列リテラル

エスケープなどの加工を施さない文字列を3個の二重引用符で括って表現できる様になった。未加工の文字リテラルとも呼ばれる。

#### 汎用属性

属性の型が型引数を持てる様になった。

#### パターンマッチングの拡張

リストや配列に対するパターンマッチが可能になった。

また、`Span<char>`や`ReadOnlySpan<char>`に対して文字列を用いたパターンマッチが可能になった。

#### ジェネリック型数値演算

型引数に「数値型または数値型に類似している型」である事を示す制約を付け加える機能が導入された。また、それに呼応して下記の変更が行われた。

- 明示的な論理シフト演算子(`>>>`演算子)が追加された。
- シフト演算子の右側の引数の型に対する制限の撤廃され、`int`型以外の型を指定できる様になった。
- `checked`演算子のオーバーロードができる様になった。
- インターフェースのメソッドに対して`static abstract`キーワード(静的抽象)と`static virtual`キーワード(静的仮想)を指定できる様になった。
- インターフェース内に演算子を定義できる様になった。

ジェネリック型数値演算を用いた一例を下記に示す。

#### その他の仕様

- UTF-8 文字列リテラル
- 文字列補間式の改行
- ファイルローカル型
- 必須メンバー
- auto-default 構造体(構造体の未初期化のフィールド変数が自動的に既定値に初期化される)
- `nameof` のスコープ拡張
- `IntPtr` に別名 `nint`、`UIntPtr` に別名 `nuint` が付いた
- `ref` フィールド
- `scoped ref` 変数
- メソッドグループからデリゲートへの変換の改善
- 警告ウェーブ 7

### C# 12.0からの仕様

C# 12.0で追加された仕様は以下の通り。

#### クラスと構造体のプライマリコンストラクター

レコード型(`record`)以外のクラス(`class`)と構造体(`struct`)でプライマリコンストラクターが使えるようになった。

#### コレクション式

配列、コレクション、`Span<T>`などの初期化の記法が共通の記法(`[]`)で書けるようになった。

#### スプレッド演算子

コレクション式で複数のコレクションをインライン展開できる新しい演算子(`..`)が追加された。

#### その他の仕様

- インライン配列
- 既定のラムダ パラメーター
- 任意の型の別名設定
- `ref readonly` パラメーター
- 試験段階の属性
- インターセプター

### C# 13.0からの仕様

C# 13.0で追加された仕様は以下の通り。

#### 新しいエスケープシーケンス

エスケープ文字を表すエスケープシーケンスとして`\e`が追加された。これに従って`\x1b`の使用は非推奨となった。

#### 暗黙的なインデックスアクセス

オブジェクト初期化子においても`^`演算子を用いたアクセスが可能となった。これにより、初期化子内でも配列やリストなどの末尾から値へアクセスできる。

#### paramsコレクション

コレクション式に対応している型であれば、引数に`params`修飾子を付けられる様になった。

#### その他の仕様

- メソッド グループでの自然型
- 部分プロパティ
- `ref` 構造体のインターフェイス実装
- `OverloadResolutionPriority` 属性(オーバーロードの解決優先度を変更できる)
- `Lock` クラスに対する `lock`
- イテレーター・非同期メソッド内の `ref`/`unsafe`
- インターセプター
- コレクション式の改善

## 実装

C#の言語仕様は標準化団体Ecma Internationalを通じて公開・標準化されており、第三者がマイクロソフトとは無関係にコンパイラや実行環境を実装することができる。

### コンパイラの実装

現段階で、C#コンパイラの実装は次の5つが知られている。

- マイクロソフト製
  - Visual Studio 2015 以降で使用されている、.NETコンパイラプラットフォーム (コードネーム Roslyn)。ApacheライセンスのオープンソースプロジェクトでGitHubで公開されている。Windows、macOS、Linuxで動作する。C#のコンパイラはC#、VB.NETのコンパイラはVB.NETで実装されている。以前のコンパイラと比べて、リファクタリングやIDE、スクリプティングなどへの利用が可能なAPIが公開されており、コンパイラ以外への様々な応用が可能。
  - Visual Studio 2013 まで使われていた、マイクロソフトによるVisual C# コンパイラ。
  - 2006年のC# 2.0当時の、マイクロソフトによるShared Source Common Language Infrastructure。共通言語基盤 (CLI) とC#コンパイラがソースコードで公開されている。
- Mono ProjectによるMono内の Mono Compiler Suite (mcs)。
- 2012年まで開発されていた、DotGNU ProjectによるPortable.NET内の the C-Sharp code compiler (cscc)。

### 実行環境の実装

- マイクロソフト
  - .NET Runtime
  - .NET Framework Runtime
- Mono Project
  - Monoランタイム
- カプコン
  - RE ENGINEに実装されている REVM

## 名称

- ECMA-334 3rd/4th/5th edition によると、C# は「C Sharp」(シーシャープ)と発音し、LATIN CAPITAL LETTER C (U+0043) の後に NUMBER SIGN # (U+0023) と書く。 音楽のシャープ (♯, MUSIC SHARP SIGN (U+266F)) ではなくナンバーサイン (#) を採用したのは、フォントやブラウザなどの技術的な制約に加え、ASCIIコードおよび標準的キーボードには前者の記号が存在しないためである。
- "#"接尾辞は、他の.NET言語にも使用されており、J#(Javaのマイクロソフトによる実装)、A#(Adaから)、F#(System Fなどから)が含まれる。また"#"接尾辞はGtk#(GTKなどのGNOMEライブラリの.NETラッパ)、Cocoa#(Cocoa (API)のラッパ)などのライブラリにも使用されている。そのほか、SharpDevelopなどの"Sharp"を冠する関連ソフトウェアも存在する。
- C#という名称の解釈として、「(A-Gで表された)直前の音を半音上げる」という音楽記号の役割に着目し、「C言語を改良したもの」を意味したのではないか、というものがある。これは、C++の名称が「C言語を1つ進めたもの」という意味でつけられたことにも似ている。
- アンダース・ヘルスバーグは、「C#」が「C++++」(すなわち「C++をさらに進めたもの」)にみえるのが由来である、と語っている。