共用方式為


部分成員 (C# 參照)

部分成員包含一個宣告宣告,通常還有一個實作宣告宣告宣告不含主體。 實作宣告會提供成員的主體。 部分成員可讓類別設計工具提供成員攔截程序,可以由工具 (例如來源產生器) 來實作。 部分型別和成員提供一套方式,讓人類開發人員撰寫型別的一部分,而工具則撰寫型別的其他部分。 如果開發人員未提供選擇性的實作宣告,編譯器可以在編譯階段移除宣告宣告。 下列條件適用於部分成員:

  • 宣告必須以內容關鍵字 partial 作為開頭。
  • 部分型別的兩個部分中的簽章必須相符。

建構函式、完成項、多載運算子或事件宣告無法使用 partial 關鍵字。 在 C# 13 之前,屬性或索引子無法使用 partial

以下案例並不需要部分方法,即有實作宣告:

任何不符上述所有限制的成員 (例如 public virtual partial void 方法),都必須提供實作。 部分屬性和索引子必須具有實作。

下列範例所示為符合上述限制的部分方法:

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}");
}

部分成員在與來源產生器結合使用時也很實用。 例如,下列模式可用來定義 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
        }
    }
}

上述範例所示為必須具有實作宣告的部分方法。 在組建中,規則運算式來源產生器會建立實作宣告。

下列範例所示為類別的宣告宣告和實作宣告。 因為方法的傳回型別不是 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;
    }
}

上述範例說明這兩種宣告結合的規則:

  • 簽章相符:一般而言,宣告宣告和實作宣告的簽章必須相符。 這包括方法、屬性、索引子和個別存取子上的存取範圍修飾詞。 其中包含所有參數的參數型別和類參照修飾詞。 傳回型別和任何類參照修飾詞都必須相符。 Tuple 成員的名稱必須相符。 不過,某些規則是有彈性的:
    • 宣告宣告和實作宣告可能有不同的可為 Null 註釋設定。 也就是說,可能一個是可為 Null 遺忘式,另一個是啟用可為 Null
    • Null 屬性的差異若與遺忘式 Null 屬性無關,就會產生警告。
    • 預設參數值不需相符。 如果方法或索引子的實作宣告宣告了預設參數值,編譯器會發出警告。
    • 參數名稱不相符時,編譯器會發出警告。 發出的 IL 包含宣告宣告的參數名稱。
  • 文件註解:任一種宣告都可能包含文件註解。 如果宣告宣告和實作宣告都包含文件註解,系統會納入實作宣告中的註解。 在上述範例中,文件註解包括:
    • 如果是 Capacity 屬性,註解會取自實作宣告。 兩個宣告都有 /// 註解時,系統會使用實作宣告的註解。
    • 如果是索引子,註解會取自宣告宣告。 實作宣告不包含任何 /// 註解。
    • 如果是 TryGetAt,註解會取自實作宣告。 宣告宣告不包含任何 /// 註解。
    • 產生的 XML 具有所有 public 成員的文件註解。
  • 大部分屬性宣告都會合併。 不過,所有呼叫端資訊屬性都是以 AllowMultiple=false 來定義。 編譯器會識別出宣告宣告的任何呼叫端資訊屬性。 實作宣告的所有呼叫端資訊屬性都會遭到忽略。 如果您對實作宣告新增呼叫端資訊屬性,編譯器會發出警告。

另請參閱