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

泚

この蚘事では、Null 蚱容参照型に぀いお説明したす。 たた、Null 蚱容倀型を宣蚀するこずもできたす。

null 蚱容察応コンテキスト内のコヌドでは 、null 蚱容参照型を䜿甚したす。 Null 蚱容参照型、Null スタティック分析の譊告、Null 免陀挔算子は、オプションの蚀語機胜です。 既定では、すべおオフになっおいたす。 プロゞェクト レベルで null 蚱容コンテキスト を制埡するには、ビルド蚭定を䜿甚するか、プラグマを䜿甚しおコヌドで制埡したす。

C# 蚀語リファレンスには、C# 蚀語の最新リリヌス バヌゞョンが蚘茉されおいたす。 たた、今埌の蚀語リリヌスのパブリック プレビュヌの機胜に関する初期ドキュメントも含たれおいたす。

このドキュメントでは、蚀語の最埌の 3 ぀のバヌゞョンたたは珟圚のパブリック プレビュヌで最初に導入された機胜を特定したす。

ヒント

C# で機胜が初めお導入された時期を確認するには、 C# 蚀語バヌゞョン履歎に関する蚘事を参照しおください。

重芁

すべおのプロゞェクト テンプレヌトで、プロゞェクトに察しお の null 蚱容コンテキスト が有効になりたす。 以前のテンプレヌトで䜜成されたプロゞェクトにはこの芁玠は含たれたせん。これらの機胜は、プロゞェクト ファむルで有効にするか、プラグマを䜿甚しない限りオフです。

Null 蚱容認識コンテキストでは、次の芏則が䜿甚されたす。

  • null 以倖の倀で T 参照型の倉数を初期化する必芁があり、 null可胜性のある倀を割り圓おるこずはありたせん。
  • T?を䜿甚しおnull参照型の倉数を初期化するか、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

倉数 notNull ず nullable はどちらも 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 蚱容コンテキストは、コンパむラが null 蚱容参照型の泚釈を凊理する方法ず、静的 null 状態分析䞭に生成される譊告を決定したす。 ヌラブルコンテキストには、泚釈 蚭定ず 譊告 蚭定の 2 ぀のフラグが含たれおいたす。

既存のプロゞェクトでは、泚釈 ず 譊告 蚭定の䞡方が既定で無効になっおいたす。 .NET 6 (C# 10) 以降では、new プロゞェクトでは、䞡方のフラグが既定で有効になりたす。 null 蚱容コンテキストの 2 ぀の異なるフラグの理由は、null 蚱容参照型の導入前の倧芏暡なプロゞェクトの移行を容易にするためです。

小芏暡なプロゞェクトの堎合は、nullable参照型を有効にし、譊告を解決しお続行するこずができたす。 ただし、倧芏暡なプロゞェクトやマルチプロゞェクト ゜リュヌションでは、そのプロセスによっお倚数の譊告が生成される可胜性がありたす。 Null 蚱容参照型の䜿甚を開始する際に、pragma を䜿甚しおファむルごずに Null 蚱容参照型を有効にするこずができたす。 System.NullReferenceException をスロヌから保護する新機胜は、既存のコヌドベヌスで有効にするず、䞭断を䌎う可胜性がありたす。

  • 明瀺的に型指定された参照倉数はすべお、null 非蚱容参照型ずしお解釈されたす。
  • ゞェネリック内の class 制玄の意味は、null 非蚱容参照型を意味するように倉曎されたした。
  • これらの新しい芏則により、新しい譊告が生成されたす。

null 蚱容泚釈コンテキストは、コンパむラの動䜜を決定したす。 null 蚱容コンテキストの 蚭定には、次の 4 ぀の組み合わせがありたす。

  • 䞡方無効: コヌドは null 蚱容未指定です。 Disable は、Null 蚱容参照型が有効になる前の動䜜ず䞀臎したす。ただし、新しい構文でぱラヌではなく譊告が生成されたす。
    • Null 蚱容の譊告は無効になっおいたす。
    • 参照型の倉数はすべお、null 蚱容参照型です。
    • null蚱容参照型を宣蚀するために?サフィックスを䜿甚するず、譊告が衚瀺されたす。
    • null 免陀挔算子 ! は䜿甚できたすが、効果がありたせん。
  • 䞡方ずも有効: コンパむラは、すべおの null 参照分析ずすべおの蚀語機胜を有効にしたす。
    • 新しい Null 蚱容のすべおの譊告が有効になりたす。
    • ? サフィックスを䜿甚しお、null 蚱容参照型を宣蚀できたす。
    • ? サフィックスのない参照型倉数は、null 非蚱容参照型です。
    • null 蚱容挔算子は、 nullの逆参照の可胜性に関する譊告を抑制したす。
  • 譊告が有効な: コンパむラはすべおの null 分析を実行し、コヌドが nullを逆参照する可胜性がある堎合に譊告を出力したす。
    • 新しい Null 蚱容のすべおの譊告が有効になりたす。
    • null蚱容参照型を宣蚀するために?サフィックスを䜿甚するず、譊告が衚瀺されたす。
    • 参照型の倉数はすべお null にするこずができたす。 ただし、 サフィックスを䜿甚しお宣蚀しない限り、メンバヌは、すべおのメ゜ッドが巊䞭かっこで囲たれた "null 以倖" の "?" になりたす。
    • null 免陀挔算子 ! を䜿甚できたす。
  • 泚釈が有効 : コヌドが を逆参照する可胜性がある時、たたは maybe-null 匏を null 非蚱容倉数に割り圓おた時、コンパむラは譊告を出力したせん。
    • Null 蚱容の新しい譊告はすべお無効になっおいたす。
    • ? サフィックスを䜿甚しお、null 蚱容参照型を宣蚀できたす。
    • ? サフィックスのない参照型倉数は、null 非蚱容参照型です。
    • null 免陀挔算子 ! は䜿甚できたすが、効果がありたせん。

.csproj ファむルの <Nullable> 芁玠を䜿甚しお、プロゞェクトの null 蚱容泚釈コンテキストず null 蚱容譊告コンテキストを蚭定できたす。 この芁玠は、コンパむラが型の null 蚱容を解釈する方法ず、生成される譊告を構成したす。 次の衚に、蚱容される倀ず、指定されるコンテキストの抂芁を瀺したす。

Context 逆参照の譊告 割り圓おの譊告 参照のタむプ ? サフィックス ! 挔算子
disable Disabled Disabled すべお Null 蚱容です 譊告を生成したす 圱響はありたせん
enable 有効 有効 ? で宣蚀されおいる堎合を陀き、null 非蚱容です。 null 蚱容型を宣蚀したす 可胜性のあるnull割り圓おに察する譊告を抑制したす
warnings 有効 適甚なし すべお null 蚱容ですが、メ゜ッドの巊䞭括匧䜍眮で、メンバヌは not-null であるずみなされたす。 譊告を生成したす 可胜性のあるnull割り圓おに察する譊告を抑制したす
annotations Disabled Disabled ? で宣蚀されおいる堎合を陀き、null 非蚱容です。 null 蚱容型を宣蚀したす 圱響はありたせん

"無効な" コンテキスト内のコンパむルされたコヌドの参照型倉数は、"null 蚱容未指定" です。 null である倉数には、 リテラルたたは maybe-null の倉数を割り圓おるこずができたす。 ただし、"null 蚱容未指定" 倉数の既定の状態は、"null 以倖" です。

プロゞェクトに最適な蚭定を遞択したす。

  • 蚺断や新機胜に基づいお曎新したくないレガシ プロゞェクトには、"無効" を遞択したす。
  • コヌドが をスロヌする可胜性がある堎所を特定するには、System.NullReferenceExceptionを遞択したす。 コヌドが倉曎され、null 非蚱容参照型が有効になる前に、これらの譊告に察凊するこずができたす。
  • 譊告が有効になる前にデザむンの意図を衚珟するには、"泚釈" を遞択したす。
  • null 参照の䟋倖から保護する新しいプロゞェクトずアクティブなプロゞェクトには "有効" を遞択したす。

䟋:

<Nullable>enable</Nullable>

ディレクティブを䜿甚しお、゜ヌス コヌド内の任意の堎所でこれらの同じフラグを蚭定するこずもできたす。 これらのディレクティブは、倧芏暡なコヌドベヌスを移行しおいる堎合に最も圹立ちたす。

  • #nullable enable: 泚釈フラグず譊告フラグを enable に蚭定したす。
  • #nullable disable: 泚釈フラグず譊告フラグを無効にするよう 蚭定したす。
  • #nullable restore: 泚釈フラグず譊告フラグをプロゞェクト蚭定に埩元したす。
  • #nullable disable warnings: 譊告フラグを無効に蚭定 したす。
  • #nullable enable warnings: 有効にする譊告フラグを蚭定したす。
  • #nullable restore warnings: 譊告フラグをプロゞェクト蚭定に埩元したす。
  • #nullable disable annotations: 無効にする泚釈フラグを蚭定したす。
  • #nullable enable annotations: 有効にする泚釈フラグを蚭定したす。
  • #nullable restore annotations: 泚釈フラグをプロゞェクト蚭定に埩元したす。

任意のコヌド行に察しお、次のいずれかの組み合わせを蚭定できたす。

譊告フラグ 泚釈フラグ Use
プロゞェクト デフォルト プロゞェクト デフォルト デフォルト
有効にする 無効にする 分析譊告を修正する
有効にする プロゞェクト デフォルト 分析譊告を修正する
プロゞェクト デフォルト 有効にする 型の泚釈の远加
有効にする 有効にする 既に移行されおいるコヌド
無効にする 有効にする 譊告を修正する前にコヌドに泚釈を付ける
無効にする 無効にする 移行されたプロゞェクトぞのレガシ コヌドの远加
プロゞェクト デフォルト 無効にする ほずんどない
無効にする プロゞェクト デフォルト ほずんどない

これら 9 ぀の組み合わせにより、コンパむラがコヌドに察しお出力する蚺断をきめ现かく制埡できたす。 曎新しおいる任意の領域内で、さらに倚くの機胜を有効にするこずができたす。ただ察凊するこずができない远加の譊告は衚瀺されたせん。

重芁

グロヌバル null 蚱容コンテキストは、生成されたコヌド ファむルには適甚されたせん。 いずれの方法でも、Null 蚱容コンテキストは、生成枈みずしおマヌクされおいるすべおの゜ヌス ファむルに察しお "無効になりたす"。 この条件は、生成されたファむル内の API にコンパむラが泚釈を付けないこずを意味したす。 コンパむラは、生成されたファむルに察しお null 蚱容譊告を生成したせん。 ファむルは、次の 4 ぀の方法のいずれかで生成枈みずしおマヌクされたす。

  1. .editorconfig で、そのファむルに適甚されるセクションで generated_code = true を指定したす。
  2. ファむルの先頭にあるコメントに <auto-generated> たたは <auto-generated/> を配眮したす。 これは、コメント内の任意の行に配眮できたすが、コメント ブロックはファむル内の最初の芁玠である必芁がありたす。
  3. ファむル名を TemporaryGeneratedFile_ で開始したす
  4. ファむル名の末尟を .designer.cs、 .generated.cs、 .g.cs、たたは .g.i.cs にしたす。

ゞェネレヌタヌは、 #nullable プリプロセッサ ディレクティブを䜿甚しおオプトむンできたす。

既定の null 蚱容泚釈および譊告フラグトは disabled です。 この既定倀は、既存のコヌドが倉曎されず、新しい譊告を生成せずにコンパむルされるこずを意味したす。 .NET 6 以降、新しいプロゞェクトにはすべおのプロゞェクト テンプレヌトに <Nullable>enable</Nullable> 芁玠が含たれるので、これらのフラグを enabled に蚭定したす。

これらのオプションでは、null 蚱容参照型を䜿甚するように既存のコヌドベヌスを曎新するための 2 ぀の方法が提䟛されたす。

Null 蚱容コンテキストの蚭定

null 蚱容コンテキストは、2 ぀の方法で制埡できたす。 プロゞェクト レベルで、 <Nullable>enable</Nullable> プロゞェクト蚭定を远加したす。 単䞀の C# ゜ヌス ファむルで、null 蚱容コンテキストを有効にする #nullable enable プラグマを远加したす。 詳现に぀いおは、 null 蚱容戊略の蚭定を参照しおください。 .NET 6 より前の新しいプロゞェクトでは、既定の <Nullable>disable</Nullable>が䜿甚されたす。 .NET 6 以降では、新しいプロゞェクトには、プロゞェクト ファむルに <Nullable>enable</Nullable> 芁玠が含たれおいたす。

ゞェネリック

T型パラメヌタヌを null 蚱容の察応T?ずしお䜿甚するず、実際の型匕数によっお?の解釈方法が決たりたす。 次の䞀般的な宣蚀に぀いお考えおみたしょう。

public class Box<T>
{
    public T Contents { get; set; }
}

型パラメヌタヌは参照型たたは倀型に察しお䜿甚できるため、 T? の意味は呌び出し元が指定する型匕数によっお異なりたす。 次の芏則では、Tに制玄がない堎合に解決T?に぀いお説明したす。

  • 型匕数は null 非蚱容参照型です。 Box<string>の堎合、Tはstringされ、T?は察応する null 蚱容参照型であるstring?。
  • 型匕数は倀型です。 Box<int>の堎合、Tはintされ、T?も同じ倀の型intされたす。 泚釈は、型パラメヌタヌに struct 制玄がない限り、倀型には圱響したせん。その堎合、 T? は Nullable<T> (int?) を意味したす。
  • 型匕数は既に null 蚱容です。 Box<string?>の堎合、Tはstring?され、T?はただstring?。 "二重に null 蚱容" 型は取埗されたせん。

制玄 によっお、蚱可される型匕数が制限されたす。 たた、 T の䜿甚方法に関するコンパむラの理由も瀺したす。

  • where T : class には null 非蚱容参照型が必芁です。 Box<string> は蚱可されたす。 Box<string?> は譊告を生成したす。
  • where T : class? では、null 蚱容参照型たたは null 非蚱容参照型のいずれかを䜿甚できたす。 Box<string>ずBox<string?>の䞡方が蚱可されたす。
  • where T : struct には null 非蚱容倀型が必芁です。 Box<int> は蚱可されたす。 Box<int?> ではありたせん。 この制玄では、ゞェネリック手段Nullable<T>内のT?がBox<int>の堎合、T?はint?されたす。
  • where T : notnull には、null 非蚱容参照型たたは倀型が必芁です。 Box<string> ず Box<int> が蚱可されおいたす。 Box<string?> は譊告を生成したす。
  • where T : BaseType には、 BaseTypeから掟生する null 非蚱容参照型が必芁です。 ? (where T : BaseType?) を远加しお、null 蚱容掟生型も蚱可したす。

制玄は、ゞェネリック型パラメヌタヌの䜿甚方法に関するコンパむラの理由に圹立ちたす。

public static T? FirstOrDefault<T>(IEnumerable<T> source)
{
    foreach (T item in source)
    {
        return item;
    }
    return default;
}

public static void RequireNotNull<T>(T value) where T : notnull
{
    ArgumentNullException.ThrowIfNull(value);
}

public static void Generics()
{
    string? first = FirstOrDefault<string>([]);
    Console.WriteLine(first ?? "<empty>");

    RequireNotNull("not null");
}

C# 蚀語仕様

詳现に぀いおは、C# 蚀語仕様の Null 蚱容参照型に関するセクションを参照しおください。

関連項目