0Pricing
C# Academy · レッスン

NRTの有効化と理解

nullableコンテキストを有効にし、nullableとnon-nullableの参照型を理解して、コンパイラー警告を読み取ります。

「NRTの有効化と理解」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。

10億ドルの失敗

null の発明者である Tony Hoare は、これを自身の「10億ドルの失敗」と呼びました。C# では、既定ですべての参照型が null になり得るため、NullReferenceException が最も一般的な実行時クラッシュの原因になります。Nullable Reference Types(NRT)は、これをコンパイラーのレベルで解決します。

Nullable コンテキストの有効化

プロジェクトファイルでグローバルに、またはディレクティブを使ってファイル単位で NRT を有効にします。有効にすると、コンパイラーは既定で参照型を null 非許容として扱います。

<!-- In .csproj — enable for the whole project -->
<PropertyGroup>
  <Nullable>enable</Nullable>
</PropertyGroup>

// Or per-file:
#nullable enable
// ... code with NRT warnings
#nullable disable
// ... code without NRT warnings

Null 非許容参照型と Null 許容参照型

NRT を有効にすると、string は決して null にならないことを意味し、string? はnull になる可能性があることを意味します。null を null 非許容型に代入した場合や、チェックせずに null 許容型を逆参照した場合、コンパイラーが警告します。

#nullable enable

string nonNull = "Hello";    // OK
string? maybeNull = null;    // OK — explicitly nullable

nonNull = null;              // WARNING: CS8600
Console.WriteLine(maybeNull.Length); // WARNING: CS8602 — may be null

// Fix:
if (maybeNull is not null)
    Console.WriteLine(maybeNull.Length); // safe

フロー分析

コンパイラーはフロー分析を実行します。条件分岐や分岐処理を通じて null の状態を追跡し、値が null ではないと証明できる場合は警告を抑制します。

string? name = GetName();

// After null check, name is treated as non-null:
if (name is not null)
    Console.WriteLine(name.Length);  // no warning

// Same with early return:
if (name is null) return;
Console.WriteLine(name.Length);     // no warning — null was returned

// Pattern matching:
if (name is string s)
    Console.WriteLine(s.ToUpper()); // no warning

Null 許容性に関する警告:CS8600–CS8629

理解しておくべき主な NRT 警告は次のとおりです。CS8600(null を null 非許容型に代入)、CS8602(null の可能性がある値の逆参照)、CS8603(null 非許容型に対する null の返却)、CS8618(null 非許容フィールドの未初期化)。

#nullable enable

public class Order
{
    public string CustomerName { get; set; } // CS8618: not initialized
    public string? TrackingNumber { get; set; } // OK — nullable

    public Order(string name)
    {
        CustomerName = name; // now initialized — CS8618 gone
    }
}

string? s = GetValue();
Console.WriteLine(s.Length); // CS8602: s might be null

Null 非許容フィールドの初期化

コンストラクターで null 非許容のフィールドまたはプロパティが設定されていない場合、CS8618 が発生します。宣言時に初期化する、コンストラクターで必須にする、または DI や ORM のパターンでは null 許容抑制演算子を使用する、といった解決方法があります。

// Option 1: Initialize in declaration
public string Name { get; set; } = "";

// Option 2: Require via constructor
public class Product
{
    public string Name { get; }
    public Product(string name) => Name = name;
}

// Option 3: null-forgiving for ORM entities
public string Name { get; set; } = null!;
// null! tells compiler "trust me, this will be set by EF Core"

ジェネリック型での Null 許容性

ジェネリック型パラメーターには、null 非許容という制約を付けられます。where T : notnull 制約により、T が決して null にならないことを保証できます。

// Without constraint: T could be nullable
public T? Find<T>(int id) { ... }

// With notnull: T must be a non-nullable type
public T FindRequired<T>(int id) where T : notnull
{
    var result = InternalFind<T>(id);
    return result ?? throw new KeyNotFoundException();
}

// T? is meaningful only when T is known to be non-nullable
public T? FindOrDefault<T>(int id) where T : class { ... }

インターフェイスとオーバーライドでの Null 許容性

インターフェイスを実装したりメソッドをオーバーライドしたりする場合、null 許容性のアノテーションを一致させる必要があります。コンパイラーは、実装がインターフェイスの宣言以上に null 非許容であることを確認します。

public interface IRepository<T>
{
    T? FindById(int id);       // may return null
    T GetOrThrow(int id);      // never null
}

// Implementation:
public class ProductRepo : IRepository<Product>
{
    public Product? FindById(int id)  => _db.Find(id);
    public Product  GetOrThrow(int id) =>
        _db.Find(id) ?? throw new KeyNotFoundException();
}

Null 許容値型と Null 許容参照型

int?(Nullable<int>。C# 8 より前から存在する値型のラッパー)と、string?(NRT のアノテーション。コンパイル時のみ使用され、実行時のオーバーヘッドはない)を混同しないでください。

// Nullable value type (runtime Nullable<int>)
int? age = null;
bool hasValue = age.HasValue;
int value  = age.GetValueOrDefault();

// Nullable reference type (compile-time annotation only)
string? name = null;
// string? has NO runtime wrapper — it's just a compile-time hint
// null check is still needed at runtime
if (name is not null)
    Console.WriteLine(name.ToUpper());

! による警告の抑制

null 許容抑制演算子(!)は、コンパイラーよりも開発者のほうが正確に判断できる場合に、特定の null 許容性に関する警告を抑制します。使用は控えめにし、安全である理由を記録してください。

// Use ! when you know the value cannot be null
var user = _db.Users.FirstOrDefault(u => u.Email == email);
var name = user!.Name; // user is guaranteed by business logic

// EF Core navigation properties set by the framework:
public class Order
{
    public Customer Customer { get; set; } = null!; // set by EF Core
}

実践例:Null 許容 API レスポンス

JSON レスポンスにフィールドが含まれる場合と含まれない場合がある API ラッパーでは、null 許容性のアノテーションによって意図を明確に伝えられます。

#nullable enable

public class WeatherResponse
{
    public string City { get; set; } = "";     // always present
    public double Temperature { get; set; }     // always present
    public string? Description { get; set; }    // optional field
    public string? AlertMessage { get; set; }   // only when there's an alert
}

// Consumer:
var weather = await api.GetWeatherAsync("London");
Console.WriteLine(weather.City);            // safe
Console.WriteLine(weather.Description?.ToUpper() ?? "N/A"); // safe null-handling

クイックチェック

Nullable Reference Types(string?)には、通常の参照型(string)と比べてどのような実行時オーバーヘッドがありますか。

まとめ:NRT の有効化と理解

重要なポイント:

  • .csproj で <Nullable>enable</Nullable> を指定するとグローバルに有効化できる
  • string = null にならない。string? = null になる可能性がある
  • フロー分析によって、分岐や戻り値を通じて null の状態が追跡される
  • NRT のアノテーションはコンパイル時のみ使用され、実行時のオーバーヘッドはゼロ
  • CS8618:コンストラクターで null 非許容フィールドを初期化するか、ORM では = null! を使用する
  • ! の使用は控えめにし、null 許容抑制が安全である理由を記録する

よくある質問

「NRTの有効化と理解」レッスンは無料ですか?

はい。「NRTの有効化と理解」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。

「NRTの有効化と理解」で何を学びますか?

nullableコンテキストを有効にし、nullableとnon-nullableの参照型を理解して、コンパイラー警告を読み取ります。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C# Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「NRTの有効化と理解」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC# Academyレッスンでコードを書いて実行できますか?

はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. NRTの有効化と理解
  2. アノテーション:?、!、MaybeNullとNotNull
  3. Null条件演算子とNull合体演算子
  4. コードベースのNRTへの移行
← C# Academyに戻る