分享方式:


部分類別和方法 (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
  • 泛型型別參數屬性
  • 類別屬性
  • 成員

例如,請考慮下列宣告:

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() { }
}

部分方法

部份類別或結構可包含部份方法。 類別的一個組件包含方法簽章。 可在相同組件或另一個組件中定義實作。

當簽章遵守下列規則時,就不需要實作部份方法:

  • 此宣告不包含任何存取修飾詞。 此方法預設具有 private 存取權。
  • 傳回型別是 void
  • 沒有任何參數具有 out 修飾元。
  • 此方法宣告不能包含下列任何修飾元:

沒有任何實作時,此方法與方法的所有呼叫都會在編譯時間遭到移除。

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

Partial 方法可讓類別的一部分實施者宣告方法。 類別的另一個部分實施者可以定義該方法。 在兩種情況下此分離十分有用:產生重複使用程式碼的範本和來源產生器。

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

// Implementation in file2.cs
partial void OnNameChanged()
{
  // method body
}
  • Partial 方法宣告必須以內容關鍵字 partial 作為開頭。
  • 部分類型其兩個部分中的 partial 方法特徵標記必須相符。
  • 部分方法可以有 staticunsafe 修飾詞。
  • 部分方法可以為泛型。 定義和實作方法宣告的條件約束必須相同。 參數和型別參數名稱在實作宣告中不必相同,但在定義宣告中則需相同。
  • 您可以對已定義和實作的部份方法進行委派,但不能委派給沒有實作的部份方法。

C# 語言規格

如需詳細資訊,請參閱 C# 語言規格中的部份型別部份方法。 語言規格是 C# 語法及用法的限定來源。 部份方法的其他功能會在功能規格中定義。

另請參閱