C# 14で追加されたfieldキーワード・拡張メンバー・null条件代入の書き方を、.NET 10で実行した結果つきで逆引き形式にまとめます。nameof(List<>)やSpanの暗黙変換も実測で確認できます。
この記事が解決する悩み
- C# 14 の新機能、名前は見かけたけど実際どの書き方で使うのか分からない
- バッキングフィールドや、既存クラスへの後付け拡張を毎回調べ直している
- .NET 10 に上げたのに C# 14 の新構文をまだ1つも使えていない
対象読者は、C# を業務で書いていて C# 12〜13 までは把握しているエンジニアです。
プロパティ・拡張メソッド・Span<T>・ラムダの基本は知っている前提で進めます。
結論
以下がまとめです。すべて .NET 10 の C# 14 で動くことを確認済みです。
// 1. バッキングフィールドを書かずに検証する
public string Name { get; set => field = value.Trim(); }
// 2. 既存の型にプロパティや演算子を後から足す
extension(Point p)
{
public double Length => Math.Sqrt((p.X * p.X) + (p.Y * p.Y));
}
// 3. null かもしれない相手に安全に代入する
maybe?.Level = 9;
// 4. ジェネリック型の名前を nameof で取る
nameof(List<>) // "List"
// 5. 配列を Span 引数にそのまま渡す
Sum(numbers); // int[] -> ReadOnlySpan<int>
// 6. 型を書かずに out 付きラムダを書く
TryParse<int> parse = (text, out value) => int.TryParse(text, out value);
以下、1つずつ実測結果つきで見ていきます。
1. バッキングフィールドを書かずにプロパティを検証するには
field キーワードを使うと、プロパティの裏にある自動生成フィールドをそのまま参照できます。
// ---- 1. field キーワード ----
public class Member
{
public Member()
{
Name = "名無し";
}
public string Name
{
get;
set => field = string.IsNullOrWhiteSpace(value) ? "名無し" : value.Trim();
}
public int Level
{
get => field;
set
{
if (value < 0)
{
throw new ArgumentOutOfRangeException(nameof(value));
}
field = value;
}
}
}
var m = new Member();
m.Name = " ";
m.Level = 3;
Console.WriteLine($"1: [{m.Name}] {m.Level}");
// 実行結果
// 1: [名無し] 3
get; と併用できるので、片方だけ自動実装のまま残せます。
空白だけの入力を既定値に落とす処理が、これだけで書けます。
2. 既存の型にプロパティや演算子を後から足すには
拡張メンバーは、拡張メソッドと同じ発想をプロパティと演算子に広げた機能です。
// ---- 2. 拡張メンバー ----
public readonly record struct Point(double X, double Y);
public static class PointExtensions
{
extension(Point p)
{
public double Length => Math.Sqrt((p.X * p.X) + (p.Y * p.Y));
public static Point Origin => new Point(0, 0);
public static Point operator +(Point a, Point b) => new Point(a.X + b.X, a.Y + b.Y);
}
extension<T>(IEnumerable<T> source)
{
public bool IsEmpty => !source.Any();
}
}
Point a = new Point(3, 4);
Point b = new Point(1, 2);
Console.WriteLine($"2: {a.Length} {Point.Origin} {a + b} {new[] { 1 }.IsEmpty}");
// 実行結果
// 2: 5 Point { X = 0, Y = 0 } Point { X = 4, Y = 6 } False
拡張ブロックは extension(レシーバー) で始まり、その中にメソッド・プロパティ・演算子・静的メンバーを書きます。
元の型に手を入れずに a + b を定義できるのが、拡張メソッドとの大きな違いです。
3. null かもしれないオブジェクトに安全に代入するには
null 条件演算子 ?. が、C# 14 から代入の左辺でも使えます。
Member? maybe = null;
maybe?.Level = 9;
Console.WriteLine($"3a: {maybe is null}");
maybe = new Member();
maybe?.Level = 9;
Console.WriteLine($"3b: {maybe!.Level}");
// 実行結果
// 3a: True
// 3b: 9
相手が null のときは何も起きず、例外にもなりません。
if 文で囲む必要がなくなるので、初期化処理の見通しが良くなります。
4. ジェネリック型の名前を nameof で取るには
未バインドのジェネリック型を nameof に渡せるようになりました。
Console.WriteLine($"4: {nameof(List<>)} {nameof(Dictionary<,>)} {nameof(Point)}");
// 実行結果
// 4: List Dictionary Point
型引数を書かずに済むので、ログや例外メッセージに型名を埋め込むのが楽になります。
5. 配列を Span 引数にそのまま渡すには
配列・Span<T>・ReadOnlySpan<T> の間の変換が、言語組み込みの暗黙変換になりました。
private static int Sum(ReadOnlySpan<int> values)
{
int total = 0;
foreach (int v in values)
{
total += v;
}
return total;
}
private static string Describe<T>(ReadOnlySpan<T> values) => $"len={values.Length}";
int[] numbers = { 1, 2, 3 };
Span<int> span = numbers;
ReadOnlySpan<int> ro = span;
Console.WriteLine($"5: {Sum(numbers)} {ro.Length} {Describe(numbers)}");
// 実行結果
// 5: 6 3 len=3
オーバーロード解決だけでなく、ジェネリックメソッドの型推論でも効きます。
Describe<T>(ReadOnlySpan<T>) に int[] をそのまま渡して T が int に決まるのは、C# 14 からです。
6. 型を書かずに out 付きラムダを書くには
ラムダのパラメータに out などの修飾子を付けても、型を省略できるようになりました。
private delegate bool TryParse<T>(string text, out T value);
TryParse<int> parse = (text, out value) => int.TryParse(text, out value);
Console.WriteLine($"6: {parse("42", out int n)} {n}");
// 実行結果
// 6: True 42
型はデリゲート型から決まるので、out int value と書き分ける必要がありません。
つまずきポイント
- 拡張ブロックにフィールド・インデクサ・イベントは置けない。コンパイラは CS9282「このメンバーは拡張ブロックでは使用できません」を出す
- 静的拡張メンバーは拡張クラス名から呼べない。
PointExtensions.Originは CS1929 になり、Point.Originと書く必要がある fieldを使った非 null 許容プロパティをコンストラクタで初期化しないと CS9264 が出るmaybe?.Level = 9;の後でもコンパイラはmaybeを null かもしれない扱いにする。maybe!.Levelと書かないと CS8602 になる- LangVersion 13 では CS9260「機能 ‘field キーワード’ は C# 13.0 では使用できません。14.0 以上の言語バージョンを使用してください」が出る
検証環境
| OS | Windows 11 (build 10.0.26200) |
|---|---|
| CPU | AMD Ryzen 9 PRO 8945HS w/ Radeon 780M Graphics |
| メモリ | 28GB |
| 言語/ツール | .NET SDK 10.0.201 / C# 14.0 / net10.0 |
| 使用コマンド | dotnet –list-sdks / dotnet build / dotnet run –no-build |
| 測定日 | 2026-09-19 |
各セクションに載せているコードと実行結果は、すべてこの環境で実際に実行したものです。環境が異なると挙動が変わることがあります。

まとめ
用途別にまとめます。
| やりたいこと | 書くもの | 備考 |
|---|---|---|
| プロパティの値を検証する | field |
get; と併用できる |
| 型に後付けでプロパティ・演算子を足す | extension(レシーバー) { } |
フィールド・インデクサ・イベントは不可 |
| null かもしれない相手に代入する | ?. = |
null なら何もしない |
| ジェネリック型の名前を取る | nameof(List<>) |
型引数は書かない |
| 配列を Span 引数へ渡す | そのまま渡す | 型推論にも効く |
| out 付きラムダを書く | (text, out value) => |
型はデリゲートから決まる |
C# 14 は、これまで書きづらかった場所を埋める機能が中心です。
まずは field と ?. の2つから試すのがおすすめですよ。
【広告】お名前.comならドメイン取得が格安。![]()
参考
本文の記述は以下の一次情報を確認して書いています。
- C# 14 の新機能(Microsoft Learn)
- extension キーワード — 拡張メンバーの宣言(C# リファレンス)
- field キーワード(C# リファレンス)
- C# 言語バージョンの構成(LangVersion)
- 拡張メソッド(C# プログラミング ガイド)
- .NET 10 の新機能(Microsoft Learn)
あわせて読みたい
- 【Java】JDK 27 逆引き — LazyConstant・プリミティブ型パターン
- 【Kotlin】Kotlin 2.4.20 完全ガイド — SwiftエクスポートとWasm対応
- 【Rust】非同期クロージャ(async || {})の書き方・移行ガイド
- 【OSS】OpenCode 入門ガイド — OSS AIコーディングエージェントの使い方
【広告】このサイトはConoHa WINGで運営しています。安定した高速サーバーで快適にブログを書けています。いつもありがとう!!![]()

コメント