C#を用いたアプリケーション開発において、変数名やクラス名などの識別子を決定する際に必ず意識しなければならないのが「予約語」の存在です。

予約語はC#のコンパイラがプログラムの構造を解析するためにあらかじめ定義している特別な単語であり、開発者がこれらを自由に識別子として利用することは制限されています。

本記事では、C#における予約語の完全なリストから、特定の場面でのみ意味を持つコンテキストキーワード、さらには予約語を識別子として使うための特殊な記法まで、実務に直結する知識を詳細に解説します。

C#における予約語の定義と役割

C#の予約語とは、言語仕様によってその意味が固定されている単語のことであり、「予約済み識別子」とも呼ばれます。

これらの単語は、条件分岐を行うifや、クラスを定義するclass、データ型を指定するintなど、プログラムの論理構造を構築するために不可欠な要素です。

もし予約語をそのまま変数名やメソッド名として使用しようとすると、コンパイラはそれを「言語構造の一部」として解釈しようとするため、構文エラーが発生します。

例えば、int class = 10; というコードは、コンパイラが class をクラス定義の開始と認識してしまうため、ビルドに失敗します。

このように、予約語を正しく把握することは、無用なコンパイルエラーを回避し、スムーズなコーディングを実現するための基本となります。

予約語とコンテキストキーワードの違い

C#のキーワードには、大きく分けて「予約済みキーワード」と「コンテキストキーワード」の2種類が存在します。

  1. 予約済みキーワード (Reserved Keywords): プログラムのどの場所であっても識別子として使用できない単語です。
  2. コンテキストキーワード (Contextual Keywords): 特定のコードブロック内(特定の文脈内)でのみ特別な意味を持ち、それ以外の場所では識別子として使用できる単語です。

コンテキストキーワードは、C#がバージョンアップを重ねる中で、既存のプログラムとの互換性を保ちながら新しい機能を追加するために導入されました。

例えば、varget は、特定の構文以外では変数名として利用することが可能です。

C#の予約済みキーワード一覧

C#で定義されている主要な予約済みキーワードを、その役割ごとに分類して紹介します。

これらはどのような状況下でも、通常の識別子として使用することはできません。

型に関するキーワード

値型や参照型、あるいはデータの性質を定義するためのキーワードです。

キーワード概要
bool真偽値 (true/false) を表す型
byte8ビット符号なし整数
charUnicode文字
classクラスを宣言する
decimal高精度の10進浮動小数点数
double倍精度浮動小数点数
enum列挙型を宣言する
float単精度浮動小数点数
int32ビット符号付き整数
long64ビット符号付き整数
objectすべての型のルートとなる基本型
sbyte8ビット符号付き整数
short16ビット符号付き整数
string文字列型
struct構造体を宣言する
uint32ビット符号なし整数
ulong64ビット符号なし整数
ushort16ビット符号なし整数
void戻り値がないことを示す

修飾子に関するキーワード

クラス、メソッド、変数の動作やアクセス範囲を制御するためのキーワードです。

キーワード概要
abstract抽象クラスや抽象メンバーを定義する
const定数を宣言する
extern外部で実装されたメソッドを宣言する
internal同一アセンブリ内からのみアクセス可能にする
newインスタンス生成、または継承メンバーの隠蔽
override基底クラスのメソッドを再定義する
private同一クラス内からのみアクセス可能にする
protected同一クラスまたは派生クラスからアクセス可能にする
publicどこからでもアクセス可能にする
readonly読み取り専用のフィールドを定義する
sealedクラスの継承やメソッドのオーバーライドを禁止する
static静的メンバーを定義する
virtualオーバーライド可能なメソッドを定義する
volatileフィールドが複数のスレッドによって変更される可能性があることを示す

ステートメントと制御フロー

プログラムの実行順序を制御するためのキーワードです。

キーワード概要
as型のキャスト(失敗時にnullを返す)
base親クラスのインスタンスを参照する
breakループやswitch文を抜ける
caseswitch文のラベル
catch例外を捕捉する
continueループの次の反復へジャンプする
defaultswitch文のデフォルト値、または型の初期値
dodo-whileループの開始
elseif文の条件が偽の場合の処理
finally例外の有無にかかわらず実行されるブロック
forforループの開始
foreachコレクションの各要素に対するループ
goto指定したラベルへジャンプする
if条件分岐の開始
inforeach内での反復、または参照渡し引数
is型の互換性をチェックする
lockスレッド排他制御を行う
returnメソッドから値を返し、呼び出し元に戻る
switch多方向分岐の開始
this現在のインスタンスを参照する
throw例外をスローする
try例外監視ブロックの開始
typeof型のSystem.Typeオブジェクトを取得する
usingリソースの破棄を保証する、または名前空間のインポート
while条件が真の間ループする

コンテキストキーワードの仕組みと注意点

コンテキストキーワードは、「特定の構文上の位置」においてのみ予約語として機能するという特徴を持っています。

これにより、新しいキーワードが言語に追加された際にも、既存のコードでその単語を変数名として使っていた場合に動作が壊れないよう設計されています。

代表的なコンテキストキーワードには以下のものがあります。

  • var: 暗黙的な型指定の変数宣言時に使用されます。
  • get / set: プロパティのアクセサーを定義する際に使用されます。
  • yield: イテレータブロックで値を返す際に使用されます。
  • await / async: 非同期処理を記述する際に使用されます。
  • partial: クラスやメソッドの定義を分割する際に使用されます。
  • dynamic: 動的型付けを行う際に使用されます。

例えば、var は以下のように振る舞います。

C#
using System;

public class Program
{
    public static void Main()
    {
        // ここでの var はコンテキストキーワード(型推論)
        var message = "Hello, World!";
        
        // ここでの var は通常の変数名として機能する(コンテキストキーワードではない)
        int var = 100;
        
        Console.WriteLine(message);
        Console.WriteLine(var);
    }
}
実行結果
Hello, World!
100

このように、int var = 100; という記述は有効ですが、コードの可読性を著しく低下させるため、避けるのが一般的です。

予約語を識別子として使う方法(逐語的識別子)

どうしても予約語を識別子(変数名、メソッド名など)として使用しなければならない場面があります。

例えば、外部ライブラリとの連携や、自動生成されたコードとの互換性を保つ必要がある場合などです。

C#では、キーワードの前に @(アットマーク)記号を付与することで、そのキーワードを識別子として扱うことができます。

これを「逐語的識別子 (Verbatim Identifiers)」と呼びます。

逐語的識別子の使用例

以下のサンプルコードでは、通常は使用できない classif を変数名として定義しています。

C#
using System;

public class KeywordTest
{
    public static void Main()
    {
        // @ を付けることで予約語を識別子として利用可能
        string @class = "プログラミングクラス";
        int @if = 2024;

        Console.WriteLine($"classの内容: {@class}");
        Console.WriteLine($"ifの内容: {@if}");
        
        // 呼び出す際も @ が必要
        DisplayValue(@class);
    }

    public static void DisplayValue(string text)
    {
        Console.WriteLine("値: " + text);
    }
}
実行結果
classの内容: プログラミングクラス
ifの内容: 2024
値: プログラミングクラス

注意点として、@ 自体は識別子の名前の一部ではありません。

コンパイルされた際、@class は単なる class という名前の識別子として処理されます。

他の .NET 言語(VB.NET など)からこのアセンブリを参照する場合、その言語側での予約語の扱いによっては、同様の回避策が必要になることがあります。

命名規則とエラーを回避するためのベストプラクティス

予約語の衝突を避け、かつ保守性の高いコードを書くためには、C#の標準的な命名規則に従うことが極めて重要です。

1. 意味のある名前を付ける

単なる @int@string といった名前ではなく、その変数が何を表しているのかを具体的に示す名前を付けます。

  • 不適切な例: int @for = 10;
  • 適切な例: int loopCount = 10;

2. パスカルケースとキャメルケースの使い分け

C#では一般的に、クラス名やメソッド名にはパスカルケース (PascalCase)ローカル変数や引数名にはキャメルケース (camelCase) を使用します。

  • クラス名: UserAccount
  • メソッド名: CalculateTotalAmount
  • ローカル変数名: userName

予約語の多くは小文字で構成されているため、パスカルケース(先頭が大文字)を採用するだけで、予約語との衝突は自然に回避されることが多いです。

例えば、class は予約語ですが、Class というクラス名を定義することは可能です(ただし、混同しやすいため推奨はされません)。

3. @ prefix の使用は最小限に留める

@ を使用すれば予約語を変数名にできますが、これはあくまでも「最終手段」です。

コードの読み手にとって、@event という変数が現れると、それが言語仕様のイベントハンドラなのか単なる変数なのかを一瞬で判断しづらくなります。

最新のC#で追加されたキーワード

C#は進化し続けており、比較的新しいバージョンでも新しいキーワードやコンテキストキーワードが追加されています。

これらを知っておくことで、最新の言語機能を活用した効率的な記述が可能になります。

record (C# 9.0)

データ保持に特化したクラスの一種を定義するコンテキストキーワードです。

不変性(イミュータビリティ)を持つオブジェクトを簡潔に記述できます。

init (C# 9.0)

オブジェクトの初期化時のみ値を設定できるプロパティアクセサーです。

nint / nuint (C# 9.0)

プラットフォームのポインタサイズに応じた整数型(ネイティブ整数)を定義します。

required (C# 11)

オブジェクト初期化時にそのプロパティの設定を必須にする修飾子です。

C#
public class Person
{
    // C# 11 の required キーワード
    public required string Name { get; init; }
    public int Age { get; set; }
}

// 使用例
// var p = new Person(); // コンパイルエラー:Nameが未指定
var p = new Person { Name = "田中太郎" }; // 正常

予約語に関連するよくあるエラーと対処法

開発中によく遭遇する予約語関連のトラブルとその解決策をまとめました。

CS0116: 名前空間に型、フィールド、メソッドなどのメンバーを直接含めることはできません

このエラーは、予約語の打ち間違いや、クラスの外部に実行コードを記述してしまった場合に発生することがありますが、稀に予約語を変数名として使おうとした際、コンパイラが「新しい定義が始まった」と勘違いして発生することもあります。

CS1001: 識別子が必要です

int class = 5; のように予約語をそのまま使った場合、コンパイラは「型(int)の後にクラス定義(class)が来るのはおかしい」と判断し、このエラーを出すことがあります。

この場合は、変数名を変更するか、@ を付与することで解決します。

contextual keyword の誤用

例えば、var という名前のクラスを作成してしまった場合、他の場所で var x = 10; と書くと、コンパイラが「型推論のvar」なのか「独自クラスのvar」なのかを判別できなくなり、予期せぬエラーや警告を招くことがあります。

まとめ

C#の予約語は、言語の構造を支える重要な骨組みです。

これらを正しく理解し、適切に避ける(あるいは @ で制御する)ことは、堅牢なプログラムを書くための第一歩となります。

  • 予約済みキーワードは、原則として識別子に使用できない。
  • コンテキストキーワードは、特定の場所以外では識別子として利用可能だが、混乱を避けるため多用はしない。
  • どうしても予約語を名前に使いたい場合は、@ を接頭辞として付与する。
  • 最新のC#バージョンでも新しいキーワードが追加されているため、定期的な情報のアップデートが推奨される。

日々の開発においては、予約語を回避するだけでなく、C#の標準的な命名規則(パスカルケースやキャメルケース)を遵守することで、自然とキーワードとの衝突を減らし、読みやすくメンテナンス性の高いコードを維持していきましょう。