C# の null 安全性

Tip

この記事は、少なくとも 1 つのプログラミング言語を既に知っており、C# を学習している開発者向けの 基礎 セクションの一部です。 プログラミングを初めて使用する場合は、最初に「 はじめ に」チュートリアルから始めてください。

Javaまたは C++ から来ていますか? C# は、null 許容参照型を使用してコンパイル時の null 安全性を提供します。 目標は、Javaの@NonNull注釈に似ていますが、コンパイラによって適用されます。 C# には、null セーフな式を簡潔にする ?.?? などの専用の演算子もあります。

null は、値が存在しないことを表します。 メソッドの呼び出しまたはプロパティの読み取りによって、 null 参照のメンバーにアクセスしようとすると、ランタイムは NullReferenceExceptionをスローします。

// Accessing a member on null throws NullReferenceException at runtime:
// string? name = null;
// int length = name.Length; // throws NullReferenceException

// Check before you dereference:
string? name = null;
if (name is not null)
{
    Console.WriteLine($"Name has {name.Length} characters.");
}
else
{
    Console.WriteLine("Name has no value.");
}
// Output: Name has no value.

C# には、null セーフコードを記述するための 3 つの補完的なツールが提供されています。

  • null 許容値型: intbool などの値型に null を保持できるようにします
  • null 許容参照型: 参照が null かどうかをコンパイラが追跡できるようにします
  • Null 演算子: null セーフ なアクセスとフォールバック ロジックを簡潔に表す

null 許容値型

intdoubleboolなどの値型は、既定ではnullを保持できません。 型名に?を追加して、値またはを保持する nullを作成します。

int? score = null;
Console.WriteLine(score.HasValue);               // False

score = 95;
Console.WriteLine(score.HasValue);               // True
Console.WriteLine(score.GetValueOrDefault());    // 95

int? missing = null;
Console.WriteLine(missing.GetValueOrDefault(-1)); // -1

null 許容値型は、基になる値型で "データなし" を表現する必要がある場合に役立ちます。一般的なシナリオとしては、値が存在しない可能性のあるデータベース列、オプションの構成設定、まだキャプチャされていないセンサーの読み取り値などがあります。

宣言、チェック、および変換の完全な範囲については、「Nullable 値型」を参照してください。

null 許容参照型

string、配列、クラス インスタンスなどの参照型は、実行時にnullを保持できます。 Null 許容参照型 は、null 意図を明示的にし、コンパイル時に間違いをキャッチするコンパイラ機能です。

?注釈を使用して、意図を宣言します。

  • string?— この参照はnull。最初にチェックせずに逆参照すると、コンパイラによって警告が表示されます
  • string— この参照nullを割り当てると、コンパイラによって警告が表示されます。
// string?  means this reference might be null
// string   means this reference should not be null
string? nullableName = null;
string  nonNullName  = "Alice";

// ?. safely accesses a member when the reference might be null
string display = nullableName?.ToUpper() ?? "(no name)";
Console.WriteLine(display);         // (no name)

display = nonNullName.ToUpper();    // safe: nonNullName is never null
Console.WriteLine(display);         // ALICE

最新の SDK テンプレートによって作成されるすべての.NET プロジェクトでは、既定で null 許容参照型が有効になります。 有効化と注釈付けに関する完全なガイダンスについては、「null 許容参照型」を参照してください。

Null 演算子

C# にはいくつかの演算子が含まれています。この演算子を使用すると、どこでも手動の if-null ガードを使用せずに null セーフ コードを記述できます。

Operator Name Purpose
?. null 条件付きのメンバー アクセス オブジェクトが null 以外の場合にのみメンバーにアクセスする
?[] null 条件演算子を使用したインデクサーアクセス コレクションが null 以外の場合にのみ要素にアクセスする
?? Null 合体演算子 式が次の場合にフォールバック値を返します。 null
??= null 合体割り当て 変数がnullの場合のみ代入します。
is null / is not null null パターン 優先 null テスト
string? city = GetCity();

// ?. — access a member only when non-null
int? len = city?.Length;

// ?? — substitute a default when null
string display = city ?? "unknown";

// is null — preferred null test
if (city is null)
{
    Console.WriteLine("No city provided.");
}
else
{
    Console.WriteLine($"{display} ({len} chars)");
}
// Output: No city provided.

各演算子の詳細な例については、「 Null 演算子」を参照してください。

null 許容値型と null 許容参照型は、それぞれ異なる目的に使用されます

Null 許容値型と null 許容参照型は代替ではありません。 さまざまな問題を解決します。

  • "値なし" を表す必要がある値型には、 T? を使用します。たとえば、省略可能なデータベース列に int? を使用するか、まだスケジュールされていないイベントの DateTime? を使用します。
  • string? およびその他の null 許容参照注釈を使用して、参照が、nullがあることを文書化することで、実行時に NullReferenceException が発生する前に、コンパイラーが警告できるようにします。

これらの機能と null 演算子を組み合わせることで、null セーフな C# コードを記述するための完全なツール セットが提供されます。