キーワード (C Sharp)

この項目では、プログラミング言語の1つであるC#におけるキーワードに関して説明する。

この項目は、プログラムの細かい説明には立ち入らず、他の言語と比較できるような説明を目的としている。

## C#のキーワードの特徴
C#にはいわゆる予約語としてのキーワードの他、
特定の文脈においてだけ意味を持つ文脈キーワードを持つ。

### 予約語としてのキーワード
以下の77語が、予約語としてのキーワードとして指定されている。
予約語は初めのバージョンであるC# 1.0より追加されていない。(使用可能な文脈が増えたものは存在する)

`abstract` `as` `base` `bool` `break` 
`byte` `case` `catch` `char` `checked` 
`class` `const` `continue` `decimal` `default` 
`delegate` `do` `double` `else` `enum` 
`event` `explicit` `extern` `false` `finally`
`fixed` `float` `for` `foreach` `goto` 
`if` `implicit` `in` `int` `interface` 
`internal` `is` `lock` `long` `namespace` 
`new` `null` `object` `operator` `out` 
`override` `params` `private` `protected` `public` 
`readonly` `ref` `return` `sbyte` `sealed` 
`short` `sizeof` `stackalloc` `static` `string`
`struct` `switch` `this` `throw` `true` 
`try` `typeof` `uint` `ulong` `unchecked` 
`unsafe` `ushort` `using` `virtual` `void` 
`volatile` `while` 

### 文脈キーワード
文脈キーワードは、特定の文脈以外では識別子として使用できる。
C#では文脈キーワードが積極的に利用されており、機能追加の際に度々追加されている。

以下に文脈キーワードが初めに導入されたバージョンを示す。

* C# 1.0
** 名前空間に関するもの `alias` `global`  
** プロパティ、インデクサ、イベント`add` `get` `remove` `set` `value` 
* C# 2.0
** 総称型制約 `where` 
** 部分型 `partial` 
** 反復子ブロック `yield` 
* C# 3.0
** 暗黙型 `var` 
** クエリ式  `ascending` `by` `descending` `equals` `from` `group` `into` `join` `let` `on` `orderby` `select` 
* C# 4.0
** 動的型 `dynamic` 
* C# 5.0
** 非同期処理 `async` `await` 
* C# 6.0
** nameof演算子 `nameof` 
** 例外フィルタ `when` 
* C# 7.0 
** 値の破棄 `_` 
* C# 8.0 
** 総称型null非許容制約 `notnull` 
* C# 9.0 
** record型 `record` 
** init専用アクセサ `init` `with` 
** パターンマッチング拡張 `and` `or` `not` 
** ネイティブ相互運用 `nint` `nuint` 
** 最上位レベルステートメント `args` 
* C# 11.0 
** 必須メンバー `required`
** 参照スコープ `scoped`
** ファイルローカル型 `file`

### 予約済み識別子
連続した2つのアンダースコア`__`を含む識別子は、処理系によって予約されている。例えば`__`で始まる拡張キーワードを提供する処理系があるかもしれない。

### キーワードを識別子として使用する
全てのキーワードは`@int`のように`@`で修飾することで識別子として扱うことができる。
通常の識別子も`@`で修飾することができ、修飾されていない状態の識別子と同等に扱われる。

## 型に関するキーワード

### 型名
* 型名を表すキーワードは共通型システムの型のエイリアスである。
** Javaのようなプリミティブ型とラッパークラスの区別は無い。

#### byte, sbyte, ushort, short, uint, int, ulong, long
* 8,16,32,64bitの符号有/無 整数型
** CやC++と異なり、1語で1つの整数型を表す。

#### nint <sub>(文脈)</sub>, nuint <sub>(文脈)</sub>
* ネイティブの符号有/無 整数型 (C# 9.0以降)

#### float, double
* 32,64bitの浮動小数点数型

#### decimal
* 十進浮動小数点型

#### bool
* ブーリアン型

#### char
* Unicode 16ビット文字型

#### object
* 全ての型の基底となる型

#### string
* Unicode 16ビット文字のシーケンスを表す文字列型

#### void
* 戻り値が無いことを表す
* unsafeコンテキスト内で`void*`の形式で汎用ポインタを表す

#### var <sub>(文脈)</sub>
* 初期化式から型推論を行う暗黙型

#### dynamic <sub>(文脈)</sub>
* バインドが実行時まで遅延される動的型

### ユーザ定義型のキーワード
#### class, struct
* ユーザ定義のクラス、構造体を宣言する

C++では、クラスと構造体の違いは可視性の既定値が異なるのみであるのに対し、
C#では、構造体は値型で継承不可など、クラスとの差異が大きい。

#### record <sub>(文脈)</sub>
* ユーザ定義のレコード型を宣言する (C# 9.0以降)
* ユーザ定義のレコード構造体を宣言する (C# 10.0以降)

#### interface
* ユーザ定義のインターフェイスを宣言する

#### delegate
* ユーザ定義のデリゲート型を宣言する
* 匿名メソッド式を開始する

#### enum
* ユーザ定義の列挙型を宣言する

Javaでは、列挙型がクラスの延長であるのに対し、
C#では、整数型を型安全に扱うための機能である

## 値(リテラル)
### null
* 参照型の参照先が存在しないことを表す
* Nullable型の保持する値が存在しないことを表す

### true, false
* ブーリアン型の定数を表す
* true, false演算子をオーバーロードしたクラスは、条件式として利用できる

### default
* 各型の初期値を表す
** 参照型ではnullとして扱われる
** 値型ではすべてのフィールドがゼロ初期化された状態として扱われる

## 名前空間
### namespace
* 内包するコードが、どの名前空間に所属するかを宣言する

### using
* `using 完全修飾名前空間名;`の形式で名前空間を指定することで、その名前空間の型を修飾せずに使用できる
* `using static 完全修飾型名;`の形式で完全修飾型名を指定することで、その型の静的メンバーを型名で修飾せずに使用できる
* `using エイリアス名 = 完全修飾[型/名前空間]名;`の形式で、名前空間または型のエイリアスを指定する

### global <sub>(文脈)</sub>
* `global::完全修飾[型/名前空間]名`の形式で、ルート名前空間を指定する
** ルート名前空間と現在の文脈での識別子が重複した場合に、ルート名前空間を明示できる。
* `global using 完全修飾名前空間名;`の形式で名前空間を指定することで、同一プロジェクト全体でその名前空間の型を修飾せずに使用できる (C# 10.0以降)

### alias <sub>(文脈)</sub>
* `extern alias エイリアス名;`の形式で、参照するアセンブリに外部エイリアスを指定する
** 参照する複数のアセンブリ間で名前空間が重複した場合に、いずれのアセンブリであるかを明示できる。

## 修飾子
### 可視性、アクセス可能性
#### private, internal, protected, public
* 型、メンバー宣言の際、先頭に指定することで可視性を制御する
** `private`, `private protected`, `internal`, `protected`, `protected internal`, `public`の6種類の可視性がある

C#では、未指定時の既定値は選択肢の中で最小のものとなる。
対して、Javaでは未指定時はパッケージ内から可視となる。

#### file <sub>(文脈)</sub>
* 型宣言の際、先頭に指定することで可視性を同一ファイル内に制限する (C#11以降)

#### virtual
* 仮想メンバーであることを表す
** C#ではメンバーは既定で非仮想であるため、明示的に仮想 (virtual) を宣言する必要がある

#### abstract
* 抽象クラスであることを表す
* 抽象メンバーであることを表す。抽象クラス内でのみ利用できる。C++における純粋仮想関数に相当する。

#### override
* 基底クラスのメンバーをオーバーライドすることを表す

#### new
* 基底クラスのメンバーを隠蔽することを表す

#### sealed
* シールクラスであることを表す
* シールメンバーであることを表す。`override`と同時に宣言される

#### static
* 静的メンバーであることを表す。
* 静的クラスであることを表す。静的クラスは静的メンバーのみを含む
* 静的ローカル関数であることを表す。 (C#8.0以降)

#### const
* 定数 (定数フィールド、ローカル定数) を表す

#### readonly
* コンストラクタ内で初期化され、その後変更されないフィールドを表す
* readonly構造体であることを表す。readonly構造体のフィールドは全てreadonly指定されている必要がある

#### required <sub>(文脈)</sub>
* フィールドまたはプロパティが、必須項目であり初期化しなければならないことを表す (C#11以降)

#### ref
* ref構造体であることを表す。ref構造体は常にスタックに確保され、ボックス化されない

#### volatile
* フィールドが複数のスレッドによって変更されうることを表し、単一スレッド前提の最適化を防止する。

#### extern
* メソッドが外部アセンブリ (DLL) で実装されることを表す

#### partial <sub>(文脈)</sub>
* クラスが複数のファイルに分かれて実装されていることを表す
* メソッドが同一アセンブリ内の別の場所で実装されていることを表す

## 文脈の宣言
### unsafe
* unsafe文脈を宣言する

### async <sub>(文脈)</sub>
* メソッドまたはラムダ式を修飾し、非同期文脈を宣言する

### using
* リソース解放を確実に行うブロックを宣言する

### lock
* モニターロックを行うブロックを宣言する

## 文に関するキーワード
### 制御構造
#### if, else

#### for

#### foreach, in

#### while, do

#### switch, case, default

#### break

#### continue

#### goto

#### return

#### try, catch, finally, throw

#### when <sub>(文脈)</sub>
* switch文のcaseラベルでフィルター条件を指定する
* 例外処理のcatch句でフィルター条件を指定する

#### checked, unchecked
* 整数演算のオーバーフローの有無を制御する

#### fixed
* 変数の固定を行い、ガベージコレクターによる再配置を防止する
* 構造体内に固定サイズの配列を作成する

## 総称型に関するキーワード

### in, out
* 型引数の共変性、反変性を表す

### where <sub>(文脈)</sub>
* 型引数の制約条件を表す

### new
* 型引数の制約条件の最後に`new()`を指定することで、引数無のコンストラクタが必要であることを指定する

### unmanaged <sub>(文脈)</sub>
* 型引数の制約条件に指定することで、ポインタ化可能な型であることを条件指定する

### notnull <sub>(文脈)</sub>
* 型引数の制約条件の先頭に指定することで、null非許容型であることを条件指定する

## 演算子
### new
* コンストラクタを呼び出してインスタンスを生成する

### as, is
* インスタンスの型を検査し、安全なキャストを行う

### await <sub>(文脈)</sub>
* 非同期処理を待機する
* `await foreach`の組み合わせで、非同期ストリームを待機する (C#8.0以降)

### nameof <sub>(文脈)</sub>
* 対象の変数、型、メンバーの単純名を取得する

### typeof
* 対象の型の型オブジェクトを取得する

### sizeof
* 対象の型のバイト単位のサイズを取得する

### stackalloc
* スタックにメモリを割り当てる
** unsafe文脈内において、割り当てられたメモリをポインタ型の変数に代入可能
** 割り当てられたメモリを`Span<T>`型の変数に代入可能

### with <sub>(文脈)</sub>
* 元のインスタンスの指定した箇所を書き換えた複製を作成する (C# 9.0以降)

### and <sub>(文脈)</sub>, or <sub>(文脈)</sub>, not <sub>(文脈)</sub>
* パターンマッチングにおいて、パターンの論理積・論理和・論理否定を指定する (C# 9.0以降)

## アクセスのためのキーワード
### this
* 自インスタンスのメンバーにアクセスする
* 静的メソッドの第一引数の型を修飾することで、拡張メソッドを表す

### base
* 基底クラスのメンバーにアクセスする

## 引数の評価戦略

### ref
* 参照渡しを表す

### out
* 呼び出し先で初期化される、参照渡しを表す

### in
* 読み取り専用の参照渡しを表す (C# 7.2以降)

### scoped <sub>(文脈)</sub>
* `ref`, `out`, `in` を後ろに伴って、参照のスコープをメソッド内に制限する (C#11以降)

### params
* 可変長引数を表す

## メンバー定義
### 型変換
#### explicit, implicit
* 明示的/暗黙的な型変換を定義する

### 演算子
#### operator
* 利用者定義演算子を定義する

### プロパティ、インデクサ
#### get <sub>(文脈)</sub>, set <sub>(文脈)</sub>, init <sub>(文脈)</sub>, value <sub>(文脈)</sub>
* get,setアクセサを宣言する
* initアクセサ は 初期化時限定のsetアクセサを表す (C# 9.0以降)
* valueはset,initアクセサ内で、引数を表す

### イベント

#### event
* イベントメンバーを宣言する

#### add <sub>(文脈)</sub>, remove <sub>(文脈)</sub>, value <sub>(文脈)</sub>
* カスタムイベントの実装で、add,removeアクセサを宣言する
* valueはadd,removeアクセサ内で、引数を表す

### 反復子
#### yield <sub>(文脈)</sub>
* 反復子ブロックで、値の生成と終了を指示する
**`yield return 戻り値;` : 値を生成する
**`yield break;` : 値の生成を終了する

## クエリキーワード
LINQのクエリ式で利用されるキーワードのうち、予約語は`in`のみで、他は全て文脈キーワードである。

### from <sub>(文脈)</sub>, in
* データソースを指示する
`from 範囲変数 in データソース`

### where <sub>(文脈)</sub>
* データのフィルタリングを指示する
`where 条件式`

### group <sub>(文脈)</sub>, by <sub>(文脈)</sub>
* グループ化を指示する
`group グループ化対象 by キー項目`

### join <sub>(文脈)</sub>, in, on <sub>(文脈)</sub>, equals <sub>(文脈)</sub>
* 結合を指示する
`join 範囲変数 in データソース on 左側キー項目 equals 右側キー項目 `

### select <sub>(文脈)</sub>
* クエリの結果として生成されるデータの形式を指示する
`select 生成される要素`

### into <sub>(文脈)</sub>
* グループ化や結合の結果を新たな範囲変数に格納する
`into 範囲変数`

### let <sub>(文脈)</sub>
* サブ式の結果を新たな範囲変数に格納する
`let 範囲変数 = サブ式`

### orderby <sub>(文脈)</sub>, ascending <sub>(文脈)</sub>, descending <sub>(文脈)</sub>
* 昇順または降順の並べ替えを指示する
`orderby キー項目 ascending` 
`orderby キー項目 descending`

## その他

### 1文字のアンダースコア <sub>(文脈)</sub>
* 1文字のアンダースコア`_`はC#では識別子として使用できるが、C# 7.0で導入された値の破棄では、文脈によってダミー変数として振る舞う。

Java 9でもアンダースコアがキーワードに指定された。C#では文脈による判断を行うことで破壊的変更を防いでいる。

### args <sub>(文脈)</sub>
* 最上位ステートメントにおいて、コマンドライン引数を表す (C# 9.0以降)
* 最上位ステートメントにおいては`@args`を識別子として別途定義することはできない （argsは厳密にはキーワードではなく、変数名として振る舞う）

## キーワードを使わない構文

他言語ではキーワードを利用するが、C#ではキーワードを利用しない例を示す。

### 継承
C#ではC++の継承の構文を引き継いでおり、
`:`の後ろに継承するクラスと実装するインターフェイスを`,`区切りで記述する。

* Javaでは、継承には`extends`キーワードを、実装には`implements`キーワードをそれぞれ利用する。

### プロパティ
C#では専用の構文でプロパティ宣言を行う。

* Delphi (Object Pascal) では`property`キーワードを利用する
* VB.NETでは`Property`キーワードを利用する

## 脚注

## 関連項目
* 予約語
* C#
* C#のデータ型