0Pricing
C# Academy · レッスン

コードベースのNRTへの移行

警告を有効にし、APIにアノテーションを付け、問題を修正し、誤検知を避ける段階的な移行戦略を適用します。

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

NRT 移行の課題

既存のコードベースで NRT を有効にすると、通常は数百件の警告が発生します。すべてを一度に対応する方法は危険です。代わりに段階的な移行を行い、警告を少しずつ有効にしてファイル単位で修正し、決して勢いを失わないようにします。

手順 1: 警告のみを有効にする

まずは <Nullable>warnings</Nullable> を enable の代わりに使用します。これにより、注釈のないコードをエラーとして扱わずに警告だけを有効にできるため、安全な出発点になります。

<!-- Phase 1: warnings only, no breaking change -->
<PropertyGroup>
  <Nullable>warnings</Nullable>
</PropertyGroup>

<!-- Phase 2: full enable per file as you migrate -->
<!-- Phase 3: switch to enable globally when done -->

手順 2: ファイル単位で有効にする

作業する各ファイルの先頭に #nullable enable を追加します。変更範囲を実際に編集しているファイルに限定できるため、レビューしやすくなります。

#nullable enable
// Now this file has full NRT analysis

public class OrderService
{
    private readonly IOrderRepository _repo;
    // Compiler now warns about uninitialized non-nullable fields,
    // unsafe dereferences, and assignment to non-nullable

    public OrderService(IOrderRepository repo) => _repo = repo;
}

// Other files without #nullable enable are still unchecked

警告の分類

警告は2つのカテゴリに分かれます。抑制しても安全なもの(ORM エンティティや DI で注入されるフィールド)と、実際のバグ(本当に null の値を参照している場合)です。何かを抑制する前に、これらを区別してください。

// Category 1: safe to suppress with null!
// EF Core navigation properties — set by EF, never null in practice
public class Order
{
    public Customer Customer { get; set; } = null!;
}

// Category 2: real bug — must fix
public string GetFullName()
{
    return FirstName + " " + LastName; // LastName was string? -- BUG!
}

コンストラクター警告 CS8618 の修正

CS8618 は、null 非許容プロパティがコンストラクターで設定されていない場合に発生します。推奨される修正方法は、コンストラクターで値を必須にすることです。= null! は、フレームワークによって設定される値にのみ使用します。

// BEFORE (CS8618)
public class Product
{
    public string Name { get; set; }   // warning
    public Category Category { get; set; } // warning
}

// AFTER — constructor required:
public class Product
{
    public string Name { get; set; }
    public Category Category { get; set; }

    public Product(string name, Category category)
    {
        Name = name;
        Category = category;
    }
}

レガシー API の扱い

サードパーティ製 API やレガシー API には、注釈が付いていない場合があります。その戻り値の型はoblivious(null 許容でも null 非許容でもない状態)です。明示性を保つため、戻り値を null 許容変数に代入します。

// Legacy API returns 'string' but might be null (oblivious type)
string? legacyResult = OldLibrary.GetValue(); // store as nullable
if (legacyResult is null) return;

// Or convert at the boundary:
string safe = OldLibrary.GetValue() ?? "";

// For third-party types, check if they have NRT annotations:
// NuGet packages often add nullable annotations in newer versions

#pragma による特定の警告の抑制

警告が本当に誤検知で、= null! ではコードが冗長になりすぎる場合は、特定の行に限定して #pragma warning disable を使用します。

// Suppress for a specific case with explanation:
#pragma warning disable CS8618 // ORM populates this via reflection
public DbSet<Product> Products { get; set; }
#pragma warning restore CS8618

// Or inline with a comment:
public DbSet<Order> Orders { get; set; } = null!; // set by EF Core

NRT の警告をエラーとして扱う

ファイル内のすべての警告を修正したら、<WarningsAsErrors>Nullable</WarningsAsErrors> を追加するか CI で強制し、リグレッションを防ぎます。新たな null 関連の問題があるとビルドが失敗するようになります。

<!-- After full migration: treat nullable warnings as build errors -->
<PropertyGroup>
  <Nullable>enable</Nullable>
  <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
  <!-- Or selectively: -->
  <!-- <WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors> -->
</PropertyGroup>

パブリック API に注釈を付ける

ライブラリが他のユーザーに利用される場合、NRT の注釈はパブリック API の契約の一部になります。結果が null になる可能性がある場合は T? を返し、必ず値が存在する場合は T を返します。

public interface IProductService
{
    // Contract: FindById MAY return null, GetById never does
    Product? FindById(int id);
    Product  GetById(int id);  // throws if not found

    // Collection: never null (may be empty)
    IReadOnlyList<Product> GetAll();

    // String: may be empty but not null
    string GetSummary(int id);
}

移行メトリクスと追跡

#nullable enable を含むファイル数を数えるか、CI で dotnet build 2>&1 | grep CS86 を実行して進捗を追跡します。プロジェクト全体の移行完了目標日を設定してください。

# Count NRT warnings in current build
dotnet build 2>&1 | grep -c 'CS860[0-9]\|CS861[0-9]\|CS862[0-9]'

# List files still missing #nullable enable
grep -rL '#nullable enable' src/ --include='*.cs'

# Track in CI: fail if warning count increases
# Set a budget: warnings <= N, where N decreases each sprint

クイックチェック

null 非許容プロパティへの = null! という代入は、何を意味していますか。

まとめ: NRT への移行

重要なポイント:

  • 段階的に移行します: 警告モード → ファイル単位で有効化 → 全体で有効化
  • 実際のバグは修正し、ORM や DI のパターンには = null! を使用して区別します
  • CS8618 は抑制せず、コンストラクターで値を必須にして修正します
  • 明示性を保つため、レガシー API の結果を T? 変数に代入します
  • リグレッションを防ぐため、CI で null 許容に関する警告をエラーとして扱います
  • 注釈付きのパブリック API は、利用者にとって明確な契約になります

よくある質問

「コードベースのNRTへの移行」レッスンは無料ですか?

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

「コードベースのNRTへの移行」で何を学びますか?

警告を有効にし、APIにアノテーションを付け、問題を修正し、誤検知を避ける段階的な移行戦略を適用します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

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

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

「コードベースのNRTへの移行」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

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