partial メンバー (C# リファレンス)

partial メンバーには、1 つの 宣言型宣言と、多くの場合 1 つの実装宣言があります。 宣言型宣言には本文が含まれていません。 実装宣言がメンバーの本文を提供します。 partial メンバーを使用すると、クラス デザイナーはソース ジェネレーターなどのツールで実装できるメンバー フックを提供できます。 partial 型と partial メンバーは、人間の開発者が型の一部を記述し、ツールが型の他の部分を記述する方法を提供します。 開発者がオプションの実装宣言を指定しない場合、コンパイラがコンパイル時に宣言型宣言を削除できます。 partial メンバーには次の条件が適用されます。

  • 宣言は、コンテキスト キーワード partial で始まる必要があります。
  • 部分型の両方の部分のシグネチャが一致する必要がある。

partial キーワードは、コンストラクター、ファイナライザー、オーバーロードされた演算子、またはイベント宣言では使用できません。 C# 13 より前では、プロパティまたはインデクサーで partial が許可されていませんでした。

次の場合には、実装宣言のために partial メソッドが必要ありません。

  • アクセシビリティ修飾子 (既定の private を含む) はありません。
  • void を返します。
  • out パラメーターはありません。
  • 修飾子 virtualoverridesealednew、または extern はありません。

これらのすべての制限に準拠していないメンバー (public virtual partial void メソッドなど) は、実装を提供する必要があります。 partial プロパティとインデクサーには実装が必要です。

次の例は、上記の制限に準拠する partial メソッドを示しています。

partial class MyPartialClass
{
    // Declaring definition
    partial void OnSomethingHappened(string s);
}

// This part can be in a separate file.
partial class MyPartialClass
{
    // Comment out this method and the program
    // will still compile.
    partial void OnSomethingHappened(string s) =>
        Console.WriteLine($"Something happened: {s}");
}

partial メンバーは、ソース ジェネレーターと組み合わせて使用することもできます。 たとえば、regex は、次のパターンを使用して定義できます。

public partial class RegExSourceGenerator
{
    [GeneratedRegex("cat|dog", RegexOptions.IgnoreCase, "en-US")]
    private static partial Regex CatOrDogGeneratedRegex();

    private static void EvaluateText(string text)
    {
        if (CatOrDogGeneratedRegex().IsMatch(text))
        {
            // Take action with matching text
        }
    }
}

前の例は、実装宣言が必要な partial メソッドを示しています。 ビルドの一環として、正規表現ソース ジェネレーターによって実装宣言が作成されます。

次の例は、クラスの宣言型宣言と実装宣言を示しています。 メソッドの戻り値の型は voidではなく (メソッドの戻り値の型は string)、そのアクセスが public であるため、メソッドには実装宣言が必要です。

// Declaring declaration
public partial class PartialExamples
{
    /// <summary>
    /// Gets or sets the number of elements that the List can contain.
    /// </summary>
    public partial int Capacity { get; set; }

    /// <summary>
    /// Gets or sets the element at the specified index.
    /// </summary>
    /// <param name="index">The index</param>
    /// <returns>The string stored at that index</returns>
    public partial string this[int index] { get; set; }

    public partial string? TryGetAt(int index);
}

public partial class PartialExamples
{
    private List<string> _items = [
        "one",
        "two",
        "three",
        "four",
        "five"
        ];

    // Implementing declaration

    /// <summary>
    /// Gets or sets the number of elements that the List can contain.
    /// </summary>
    /// <remarks>
    /// If the value is less than the current capacity, the list will shrink to the
    /// new value. If the value is negative, the list isn't modified.
    /// </remarks>
    public partial int Capacity
    {
        get => _items.Count;
        set
        {
            if ((value != _items.Count) && (value >= 0))
            {
                _items.Capacity = value;
            }
        }
    }

    public partial string this[int index]
    {
        get => _items[index];
        set => _items[index] = value;
    }

    /// <summary>
    /// Gets the element at the specified index.
    /// </summary>
    /// <param name="index">The index</param>
    /// <returns>The string stored at that index, or null if out of bounds</returns>
    public partial string? TryGetAt(int index)
    {
        if (index < _items.Count)
        {
            return _items[index];
        }
        return null;
    }
}

前の例は、2 つの宣言を結合する方法に関する規則を示しています。

  • 署名の一致: 一般に、宣言型宣言と実装宣言の署名が一致している必要があります。 これには、メソッド、プロパティ、インデクサー、および個々のアクセサーのアクセシビリティ修飾子が含まれます。 これには、すべてのパラメーターのパラメーター型および ref 型修飾子が含まれます。 戻り値の型と任意の ref 型修飾子が一致している必要があります。 タプル メンバー名が一致している必要があります。 ただし、一部のルールは柔軟です。
    • 宣言型宣言と実装宣言にそれぞれ異なる null 許容注釈設定を含めることができます。 つまり、1 つを null 許容未指定にして、もう 1 つを null 許容対応にすることができます。
    • null 許容未指定を伴わない null 許容の違いによって警告が生成されます。
    • 既定のパラメーター値は一致させる必要がありません。 メソッドまたはインデクサーの実装宣言で既定のパラメーター値が宣言されている場合、コンパイラは警告を発行します。
    • パラメーター名が一致しない場合、コンパイラは警告を発行します。 出力された IL には、宣言型宣言のパラメーター名が含まれています。
  • ドキュメント コメント: ドキュメント コメントはどちらの宣言からも含めることができます。 宣言型宣言と実装宣言の両方にドキュメント コメントが含まれている場合は、実装宣言からのコメントが含まれます。 前の例では、次のようなドキュメント コメントが含まれています。
    • Capacity プロパティの場合、コメントは実装宣言から取得されます。 実装宣言コメントは、両方の宣言に /// コメントがある場合に使用されます。
    • インデクサーの場合、コメントは宣言型宣言から取得されます。 実装宣言には /// コメントが含まれません。
    • TryGetAt の場合、コメントは実装宣言から取得されます。 宣言型宣言には /// コメントが含まれません。
    • 生成された XML には、すべての public メンバーに関するドキュメント コメントがあります。
  • ほとんどの属性宣言が結合されます。 ただし、すべての呼び出し情報属性AllowMultiple=false で定義されます。 コンパイラは、宣言型宣言の呼び出し元情報属性を認識します。 実装宣言のすべての呼び出し元情報属性が無視されます。 実装宣言で呼び出し元情報属性を追加すると、コンパイラによって警告が発行されます。

関連項目