C# 14の新しいfieldキーワード
C#の自動プロパティは簡素ですが、セッターに検証や変換ロジックが必要になるとすぐに、完全なプロパティを書き、手動でバッキングフィールドを使用しなければならなくなります。 一行から七行へのジャンプは、単一のガード句を追加するための急な税金です。 C# 14 では、そのギャップを埋めるために field キーワードを導入し、コンパイラがバックフィールドを管理しながら、ゲッターやセッターをカスタマイズできるようにします。
彼のビデオで"C# 14の新しいフィールドキーワード"Tim Coreyは、特徴的な問題を解決し、セッター検証の実用的な例を紹介し、アップグレードする前に知っておくべき名前競合について説明します。 私たちは、field を自信を持って独自のプロパティで使用できるように、各ステップを詳細に紹介します。
セットアップ: シンプルな人物モデル
[0:12 - 1:07] Tim は .NET 10 と Visual Studio 2026 で実行されているコンソールアプリケーションから始めます。 デモは、いくつかのプロパティを持つ Person クラスを中心に展開されます。
public required string FirstName { get; set; }
public required string LastName { get; set; }
public int Age { get; set; }public required string FirstName { get; set; }
public required string LastName { get; set; }
public int Age { get; set; }ネーミングの競合が表面化したときに関連する、プライベートフィールドによってバックアップされた Demo プロパティもあります。 Program.cs では、FirstName = "Tim" と LastName = "Corey" でインスタンスを作成し、その後、姓、年齢、およびデモ値を出力します。 すべてが期待どおりに出力されます: "Corey", 0 (デフォルトの整数)、および "テスト"。
問題: 自動プロパティは不正なデータを受け入れる
[1:23 - 2:49] Tim が null を構築後に LastName に割り当てると、問題が表面化します。
p.LastName = null;p.LastName = null;LastName は required としてマークされ、非ヌル文字列としてタイプされていますが、割り当てはコンパイルされます。 required 修飾子は、オブジェクト初期化中に値が提供されることのみを保証します。 その後、誰かがプロパティに null を設定するのを防ぐわけではありません。 その結果、ランタイムでエラーが発生せずに姓が空白になります。
これはデータの完全性における実際のギャップです。 型システムはnullable参照スキグルで警告しますが、それはコンパイルタイムのヒントであり、ランタイムのガードではありません。 アプリケーションがLastName 常に有効な文字列を含むことに依存している場合、自動プロパティだけではその契約を強制できません。
従来の修正: 手動バッキングフィールドを持つ完全なプロパティ
[2:58 - 4:19] C# 14以前、標準的な解決策は自動プロパティを手動のバッキングフィールドを持つ完全なプロパティに変換することでした:
private string _lastName;
public required string LastName
{
get => _lastName;
set => _lastName = value ?? throw new ArgumentNullException(nameof(LastName));
}private string _lastName;
public required string LastName
{
get => _lastName;
set => _lastName = value ?? throw new ArgumentNullException(nameof(LastName));
}Timさんがこれを実行し、例外が正しく発生することを確認します: "値はnullにできません。 パラメータ名: LastName." このアプローチは機能しますが、プライベートフィールドの宣言、ゲッターとセッターの結線、プロパティ名を複数行にわたって繰り返す必要があります。 単一の検証ルールのためには多くの手間です。
この場合、ゲッターは何も特別なことをしません。" それはフィールドを変更せずに返します。 それでも、自動プロパティの領域を離れるときには、構文が両側を書くことを求めるため、明示的に書く必要があります。 Timさんがこの冗長さを新しい機能の動機と捉えています。
C# 14の解決策: フィールドキーワード
[4:23 - 5:47] C# 14は中間の道を導入します。 自分でプライベートなバックフィールドを宣言する代わりに、ゲッターやセッターの中で文脈キーワード field を使用して、コンパイラ生成のバックフィールドを直接参照します。
public required string LastName
{
get;
set => field = value ?? throw new ArgumentNullException(nameof(LastName));
}public required string LastName
{
get;
set => field = value ?? throw new ArgumentNullException(nameof(LastName));
}ゲッターは、ボディを必要としない自動実装の get; にとどまります。 セッターは、検証後に受信する value を割り当てるために field を使用します。 コンパイラは、標準の自動プロパティと同様に、舞台裏でバッキングフィールドを作成し、管理します。
デモを実行すると、null の割り当てで同じ ArgumentNullException が生成されます。 動作は、手動でバックされたバージョンと同一であり、7行から、必要なものだけをカスタマイズした集中的なブロックに圧縮されます。 あなたは自動プロパティゲッターを維持し、セッターだけに論理を追加し、手動のフィールド宣言を完全にスキップします。
これは、プレーンな自動プロパティ(一行、検証なし)と完全なプロパティ(7行以上、完全な管理)との間の有用な中間ステップを提供します。 あなたのロジックがセッターだけに影響を与える場合、ゲッターも再記述するという文法的なコストを払う必要はありません。
セッターガードを用いた年齢の検証
[6:16 - 7:39] field が null チェックに限定されないことを示すために、Tim は Age プロパティに範囲検証を追加します。
public int Age
{
get;
set
{
if (value > 0 && value < 120)
field = value;
}
}public int Age
{
get;
set
{
if (value > 0 && value < 120)
field = value;
}
}ここで、セッターは範囲外の値を黙って無視します。 -5 を割り当てると、条件が失敗するため、Age はその既定値であるゼロのままであり、field は書き込まれません。 Tim は、例外をスローする代わりに、この静かなアプローチを推奨しています。しかし、セッターのボディには必要なロジックを含めることができることを示していますが、ストレージには依然として field を使用します。
パターンは広く適用されます: 数値の範囲のクランプ、文字列のホワイトスペースのトリミング、大小の正規化、またはプロパティが設定されるたびに適用されたい変換。
<h2既存のフィールド変数との名前の衝突
[7:39 - 9:43] Timさんは意図的なエッジケースを紹介します。 デモクラスには、文字通り field という名前のプライベートメンバーがあります。
private string field = "test";private string field = "test";C# 14 がアクティブになると、コンパイラはプロパティアクセサー内の field を変数ではなくキーワードとして扱います。 これは、プロパティが field を参照すると、プロパティの後ろに隠されたストレージ (空の) から密かに読み込み、"test"を含む文字列メンバーからは読み込まないことを意味します。 出力は誤りを指摘しているものはなく、警告のみを伴って空白に変更されます。
2つの回避策があります。this.field をプレフィックスに指定すると、キーワードではなくクラスレベルのメンバーを意味していることをコンパイラに伝えます。 別の方法として、@field エスケープも同様に機能します。
// Both refer to the instance variable, not the keyword
string demo => this.field;
string demo => @field;// Both refer to the instance variable, not the keyword
string demo => this.field;
string demo => @field;Tim の強い推奨は、C# 14 へのアップグレード時に field という変数をすべてリネームすることです。IDE で"すべてリネーム"をすばやく行い、曖昧さを恒久的に排除します。 競合はプロパティアクセッサ内でのみ発生します; コンストラクターとメソッドは、これらのコンテキストには暗黙のバックストレージがないため、変数名に field を予想通りに解決します。
まとめ: ボイラープレート削減、同じ制御
[10:04 - 10:28] field キーワードは、日常の C# コードにおける実際的なギャップを埋めます。 一つのガードクローズまたは変換を必要とするプロパティは、もはや手動でバッキングフィールドを追加して完全に再書く必要はありません。 あなたは論理が必要なアクセッサのみをカスタマイズし、他のものは標準の自動実装として残します。
結論
[10:28 - 10:35] まとめると:C# 14 の field キーワードがすべてのプロパティアクセサー内の暗黙のバックストアに直接アクセスできるようにします。 それを使ってセッターの検証、ゲッターの変換、または両方を追加し、カスタマイズが必要ない部分のために自動プロパティ構文を放棄しません。
アップグレード前に、コードベースを調べて field という名前の変数を見つけてリネームしてください。 この特徴が引き起こす唯一の注意点を回避するための唯一の優れた予防策です。 それを超えて、これはほとんどの開発者が既にモデルを構造化する方法に自然に合致するボイラープレートのクリーンな削減です。
例のヒント:セッターだけを検証する必要がある場合、ゲッターをプレーンな get; のままにし、ボディなしで置いておきます。 コンパイラはそれを自動プロパティのゲッターとして処理し、何も追加しない透過的なreturn文を書くのを避けます。

