次の方法で共有


Null 許容参照型 (C# リファレンス)

この記事では、Null 許容参照型について説明します。 また、Null 許容値型を宣言することもできます。

null 許容対応コンテキスト内のコードでは、 null 許容参照型を使用できます。 Null 許容参照型、Null スタティック分析の警告、Null 免除演算子は、オプションの言語機能です。 既定では、すべてオフになっています。 プロジェクト レベルで null 許容コンテキスト を制御するには、ビルド設定を使用するか、プラグマを使用してコードで制御します。

C# 言語リファレンスには、C# 言語の最新リリース バージョンが記載されています。 また、今後の言語リリースのパブリック プレビューの機能に関する初期ドキュメントも含まれています。

このドキュメントでは、言語の最後の 3 つのバージョンまたは現在のパブリック プレビューで最初に導入された機能を特定します。

ヒント

C# で機能が初めて導入された時期を確認するには、 C# 言語バージョン履歴に関する記事を参照してください。

重要

すべてのプロジェクト テンプレートで、プロジェクトに対して の null 許容コンテキスト が有効になります。 以前のテンプレートで作成されたプロジェクトにはこの要素は含まれません。これらの機能は、プロジェクト ファイルで有効にするか、プラグマを使用しない限りオフです。

Null 許容認識コンテキストでは、次の規則が使用されます。

  • null 以外の値で T 参照型の変数を初期化する必要があり、 null可能性のある値を割り当てることはありません。
  • nullを使用してT?参照型の変数を初期化するか、nullを割り当てることができますが、逆参照する前にnullに対して確認する必要があります。
  • m!のように、T?型の変数mに null 許容演算子を適用すると、変数は null 以外と見なされます。

コンパイラは、上記の規則を使用して、null 非許容参照型 T と null 許容参照型 T? の区別を適用します。 T 型の変数と T? 型の変数は、同じ .NET 型です。 次の例は、Null 非許容文字列と Null 許容文字列を宣言し、Null 免除演算子を使用して、値を Null 非許容文字列に割り当てます。

string notNull = "Hello";
string? nullable = default;
notNull = nullable!; // null forgiveness

変数 notNullnullable はどちらも String 型を使用します。 null 非許容型と null 許容型はどちらも同じ型を使用するため、複数の場所で null 許容参照型を使用することはできません。 一般に、null 許容参照型を基底クラスまたは実装インターフェイスとして使用することはできません。 オブジェクトの作成式または型テスト式で null 許容参照型を使用することはできません。 null 許容参照型をメンバー アクセス式の型として使用することはできません。 次の例は、これらのコンストラクトを示します。

public MyClass : System.Object? // not allowed
{
}

var nullEmpty = System.String?.Empty; // Not allowed
var maybeObject = new object?(); // Not allowed
try
{
    if (thing is string? nullableString) // not allowed
        Console.WriteLine(nullableString);
} catch (Exception? e) // Not Allowed
{
    Console.WriteLine("error");
}

Null 許容参照とスタティック分析

前のセクションの例は、Null 許容参照型の特性を示しています。 Null 許容参照型は新しいクラスの型ではなく、既存の参照型に対する注釈です。 コンパイラは、これらの注釈を使用して、ユーザーがコード内で発生する可能性のある Null 参照エラーを検出しやすくします。 Null 非許容参照型と Null 参照型の間には、ランタイムの違いはありません。 コンパイラは、Null 非許容参照型のランタイム チェックを追加しません。 この利点は、コンパイル時分析にあります。 コンパイラは、コード内で発生する可能性のある Null エラーの検出と修正に役立つ警告を生成します。 意図を宣言すると、コンパイラは、コードがその意図に違反したときに警告を発行します。

重要

Null 許容参照注釈では動作の変更は発生しませんが、他のライブラリではリフレクションを使用して、null 許容参照型と null 非許容参照型に対して異なるランタイム動作が生成される場合があります。 特に、Entity Framework Core は null 許容属性を読み取ります。 null 許容参照を省略可能な値として解釈し、null 非許容参照を必要な値として解釈します。

Null 許容の有効なコンテキストでは、コンパイラは、Null 許容と Null 非許容の両方の参照型の変数に対してスタティック分析を実行します。 コンパイラは、各参照変数の "null 状態" を "null ではない" または "null かもしれない" として追跡します。 Null 非許容参照の既定の状態は、"null ではない" です。 Null 許容参照の既定の状態は、"null かもしれない" です。

Null 非許容参照型の "null 状態" は "null ではない" であるため、この型は常に安全に逆参照できます。 この規則を適用するために、Null 非許容参照型が Null 以外の値に初期化されていない場合、コンパイラは警告を発行します。 ローカル変数を宣言する場所に割り当てる必要があります。 フィールド初期化子またはすべてのコンストラクターでは、すべてのフィールドに "null ではない" 値を割り当てる必要があります。 状態が "null かもしれない" である参照に、Null 非許容参照が割り当てられている場合、コンパイラによって警告が発行されます。 一般に、null 非許容参照は null ではなく 、これらの変数を逆参照しても警告は発行されません。

"null かもしれない" 式を Null 非許容参照型に割り当てると、コンパイラーによって警告が生成されます。 さらに、コンパイラでは、変数が "null ではない" 式に割り当てられるまで、それに対して警告を生成します。

null 許容参照型に null を初期化または割り当てることができます。 したがって、スタティック分析では、変数が逆参照される前に、それが "null ではない" であることを確認する必要があります。 null 許容参照が null であると判断された場合、 null 非許容参照変数に割り当てると、コンパイラ警告が生成されます。 次のクラスは、これらの警告の例を示します。

public class ProductDescription
{
    private string shortDescription;
    private string? detailedDescription;

    public ProductDescription() // Warning! shortDescription not initialized.
    {
    }

    public ProductDescription(string productDescription) =>
        this.shortDescription = productDescription;

    public void SetDescriptions(string productDescription, string? details=null)
    {
        shortDescription = productDescription;
        detailedDescription = details;
    }

    public string GetDescription()
    {
        if (detailedDescription.Length == 0) // Warning! dereference possible null
        {
            return shortDescription;
        }
        else
        {
            return $"{shortDescription}\n{detailedDescription}";
        }
    }

    public string FullDescription()
    {
        if (detailedDescription == null)
        {
            return shortDescription;
        }
        else if (detailedDescription.Length > 0) // OK, detailedDescription can't be null.
        {
            return $"{shortDescription}\n{detailedDescription}";
        }
        return shortDescription;
    }
}

次のスニペットは、このクラスを使用したときにコンパイラが警告を発行する場所を示します。

string shortDescription = default; // Warning! non-nullable set to null;
var product = new ProductDescription(shortDescription); // Warning! static analysis knows shortDescription maybe null.

string description = "widget";
var item = new ProductDescription(description);

item.SetDescriptions(description, "These widgets will do everything.");

上記の例では、コンパイラのスタティック分析で、参照変数の "null 状態" がどのように判断されるのかを示しています。 コンパイラは、null のチェックと割り当てに関する言語規則を適用して、その分析を通知します。 コンパイラは、メソッドまたはプロパティのセマンティクスについて想定することはできません。 null チェックを実行するメソッドを呼び出した場合、コンパイラでは、それらのメソッドが変数の "null 状態" に影響することを認識することはできません。 API に属性を追加して、引数と戻り値のセマンティクスについてコンパイラに通知できます。 .NET ライブラリの多くの一般的な API には、これらの属性があります。 たとえば、コンパイラは、IsNullOrEmpty を null チェックとして正しく解釈します。 "null 状態" のスタティック分析に適用される属性の詳細については、"Null 許容属性" に関する記事を参照してください。

Null 許容コンテキストの設定

null 許容コンテキストは、2 つの方法で制御できます。 プロジェクト レベルで、 <Nullable>enable</Nullable> プロジェクト設定を追加します。 単一の C# ソース ファイルで、null 許容コンテキストを有効にする #nullable enable プラグマを追加します。 Null 許容戦略の設定 に関する記事を参照してください。 .NET 6 より前の新しいプロジェクトでは、既定の <Nullable>disable</Nullable>が使用されます。 .NET 6 以降では、新しいプロジェクトには、プロジェクト ファイルに <Nullable>enable</Nullable> 要素が含まれています。

C# 言語仕様

詳細については、C# 言語仕様Null 許容参照型に関するセクションを参照してください。

関連項目