部分類別和方法 (C# 程式設計手冊)

有可能將 classstructinterface 或方法的定義,分割到兩個以上的來源檔案。 每一個來源檔案都包含型別或方法定義的一個區段,而當編譯應用程式時,就會將所有區段結合起來。

部分類別

有幾種情況需要分割類別定義︰

  • 處理大型專案時,將類別分散到不同的檔案可讓多位程式設計人員同時處理它。
  • 處理自動產生的來源時,程式碼可以加入類別,不必重新建立來源檔案。 Visual Studio 建立 Windows Forms、Webb 服務包裝函式程式碼等等時,會使用這種方法。 您可以建立使用這些類別的程式碼,不必修改 Visual Studio 建立的檔案。
  • 使用 來源產生器 在類別中產生其他功能時。

若要分割類別定義,請使用 partial 關鍵字修飾詞,如下所示︰

public partial class Employee
{
    public void DoWork()
    {
    }
}

public partial class Employee
{
    public void GoToLunch()
    {
    }
}

partial 關鍵字表示可在命名空間中定義類別、結構或介面的其他組件。 所有組件都必須使用 partial 關鍵字。 所有組件都必須可在編譯時間取得,以形成最後的型別。 所有組件必須有相同的存取範圍,例如 publicprivate 等等。

如果任何組件宣告為抽象的,則整個型別視為抽象的。 如果任何組件宣告為密封的,則整個型別視為密封的。 如果任何組件宣告基底型別,則整個型別會繼承該類別。

指定基底類別的所有組件必須一致,但省略基底類別的組件仍會繼承基底型別。 組件可以指定不同的基底介面,而最後的型別會實作部分宣告列出的所有介面。 在部分定義中宣告的任何類別、結構或介面成員都可供所有其他組件使用。 最後的型別是所有組件在編譯時期的組合。

注意

partial 修飾詞不提供委派或列舉宣告使用。

下例會顯示可為部分的巢狀型別,即使巢狀型別所在的型別不是部分本身。

class Container
{
    partial class Nested
    {
        void Test() { }
    }

    partial class Nested
    {
        void Test2() { }
    }
}

在編譯時期會合併部分型別定義的屬性。 例如,請考慮下列宣告:

[SerializableAttribute]
partial class Moon { }

[ObsoleteAttribute]
partial class Moon { }

它們與下列宣告相同:

[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }

以下是合併自所有部分型別定義︰

  • XML 註解
  • interfaces
  • 泛型型別參數屬性
  • 類別屬性
  • members

例如,請考慮下列宣告:

partial class Earth : Planet, IRotate { }
partial class Earth : IRevolve { }

它們與下列宣告相同:

class Earth : Planet, IRotate, IRevolve { }

限制

當您處理部分類別定義時要遵循數項規則︰

  • 表示同型別組件的所有部分型別定義都必須使用 partial 來修改。 例如,下列類別宣告會產生錯誤︰
    public partial class A { }
    //public class A { }  // Error, must also be marked partial
    
  • partial 修飾詞只能緊貼在關鍵字 classstructinterface 之前。
  • 部分型別定義中允許巢狀部分型別,如下例所示︰
    partial class ClassWithNestedClass
    {
        partial class NestedClass { }
    }
    
    partial class ClassWithNestedClass
    {
        partial class NestedClass { }
    }
    
  • 表示同型別組件的所有部分型別定義都必須在相同的組件和相同的模組 (.exe 或 .dll 檔案) 中定義。 部分定義不能跨越多個模組。
  • 所有部分型別定義中的類別名稱和泛型型別參數必須相符。 泛型型別可以是部分的。 每個部分宣告都必須以相同的順序使用相同的參數名稱。
  • 下列部分型別定義中的關鍵字是選擇項目,但如果出現在一個部分型別定義中,即不能與同類型的另一個部分定義中指定的關鍵字衝突︰

如需詳細資訊,請參閱型別參數的條件約束

範例

在下例中,類別的欄位和建構函式 Coords,已在一個部分類別定義中宣告,而成員 PrintCoords,則是在另一個部分類別定義中宣告。

public partial class Coords
{
    private int x;
    private int y;

    public Coords(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}

public partial class Coords
{
    public void PrintCoords()
    {
        Console.WriteLine("Coords: {0},{1}", x, y);
    }
}

class TestCoords
{
    static void Main()
    {
        Coords myCoords = new Coords(10, 15);
        myCoords.PrintCoords();

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
// Output: Coords: 10,15

下例範例示範您也可以開發部分結構和介面。

partial interface ITest
{
    void Interface_Test();
}

partial interface ITest
{
    void Interface_Test2();
}

partial struct S1
{
    void Struct_Test() { }
}

partial struct S1
{
    void Struct_Test2() { }
}

部分方法

部分類別或結構可包含部分方法。 類別的一個組件包含方法簽章。 實作可以在相同部分或另一個元件中定義。 如未提供實作,則會在編譯時期移除方法和方法的所有呼叫。 視方法簽章而定,可能需要實作。 在下列情況下,不需要部分方法才能有實作:

任何不符合上述限制的方法 (例如 public virtual partial void 方法) 都必須提供實作。 該實作可由 來源產生器提供。

部分方法可讓類別之一部分的實作者宣告方法。 類別另一個部分的實作者可以定義該方法。 有兩個案例很有用:產生重複使用程式碼的範本和來源產生器。

  • 範本程式碼:範本會保留方法名稱和簽章,讓產生的程式碼可以呼叫 方法。 這些方法會遵循限制,讓開發人員決定是否要實作 方法。 如未實作方法,則編譯器會移除方法簽章和方法的所有呼叫。 方法的呼叫,包括評估呼叫中的引數可能發生的任何結果,在執行階段沒有任何作用。 因此,部分類別中的任何程式碼都可以自由使用部分方法,即使不提供實作。 如已呼叫、但未實作方法,就不會產生任何編譯時期或執行階段錯誤。
  • 來源產生器:來源產生器會提供方法的實作。 人類開發人員通常會使用來源產生器所讀取的屬性來新增方法宣告 () 。 開發人員可以撰寫呼叫這些方法的程式碼。 來源產生器會在編譯期間執行,並提供 實作。 在此案例中,通常不會遵循可能未實作的部分方法限制。
// Definition in file1.cs
partial void OnNameChanged();

// Implementation in file2.cs
partial void OnNameChanged()
{
  // method body
}
  • 部分方法宣告的開頭必須是內容關鍵字 partial
  • 部分類型兩個部分的部分方法簽章必須相符。
  • 部分方法可以有 staticunsafe 修飾詞。
  • 部分方法可以為泛型。 條件約束放在定義部分方法宣告中,可選擇性地在實作宣告時重複。 參數和型別參數名稱在實作宣告中不必相同,但在定義宣告中要相同。
  • 您可以委派已定義且實作的部分方法,但不能委派只經定義的部分方法。

C# 語言規格

如需詳細資訊,請參閱 C# 語言規格部分型別。 語言規格是 C# 語法及用法的限定來源。

另請參閱