部分類別和方法 (C# 程式設計手冊)
類別 (Class)、結構 (Struct)、介面或方法的定義,都可以分割為兩個或兩個以上的原始程式檔 (Source File)。 每個原始程式檔都包含型別或方法定義的區段,而且所有部分會在應用程式進行編譯時組合起來。
部分類別
適合分割類別定義的情況包括:
在處理大型專案時,將類別分散到個別的檔案,即可讓多位程式設計人員同時在該專案上進行運作。
使用自動產生的原始檔時,可以將程式碼加入至類別中,而無須重新建立原始程式檔。 Visual Studio 會使用這種方法建立 Windows Form、Web 服務包裝函式程式碼等。 您可以建立使用這些類別的程式碼,而不需要修改 Visual Studio 所建立的檔案。
若要分割類別定義,請使用 partial 關鍵字修飾詞 (Modifier),如下所示:
public partial class Employee
{
public void DoWork()
{
}
}
public partial class Employee
{
public void GoToLunch()
{
}
}
partial 關鍵字表示可定義於命名空間 (Namespace) 中之類別、結構或介面的其他組件。 所有組件都必須使用 partial 關鍵字。 所有的組件必須都可在編譯時期提供使用,才能夠形成最後的型別。 所有的組件都必須有相同的存取範圍,例如 public、private 及其他。
如果有任何組件宣告為抽象,整個型別就會被視為抽象。 如果有任何組件宣告為密封,整個型別就會被視為密封。 如有任何組件宣告為基底型別 (Base Type),整個型別就會繼承該類別。
所有指定基底類別 (Base Class) 的組件都必須一致,不過省略基底類別的組件仍會繼承該基底型別。 這些組件可以指定不同的基底介面,而最後的型別會實作由所有的部分宣告列出的任何介面。 在部分定義中所宣告的任何類別、結構或介面成員,都可供其他所有組件使用。 最後型別會是編譯時期中所有組件的組合。
注意事項 |
---|
委派或列舉型別宣告中不能使用 partial 修飾詞。 |
下列範例會示範巢狀型別可以是 partial,即使這些巢狀型別所包含其中的型別並非 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 註解
介面
泛型型別參數屬性
類別屬性
成員
例如,假設宣告如下所示:
partial class Earth : Planet, IRotate { }
partial class Earth : IRevolve { }
它們相當於下列宣告:
class Earth : Planet, IRotate, IRevolve { }
限制
下面是要在使用部分類別定義時遵守的一些規則:
組成相同型別的所有部分型別定義,都必須由 partial 修飾。 例如,下列類別宣告將會產生錯誤:
public partial class A { } //public class tcA { } // Error, must also be marked partial
partial 修飾詞只能緊接在關鍵字 class、struct 或 interface 前面。
巢狀的部分型別允許出現在部分型別定義中,如下列範例所示,
partial class ClassWithNestedClass { partial class NestedClass { } } partial class ClassWithNestedClass { partial class NestedClass { } }
組成相同型別的所有部分型別定義,都必須在同一組件和模組 (.exe 或 .dll 檔案) 內定義。 部分定義無法跨多個模組。
類別名稱和泛型型別參數在所有部分型別定義中都必須相符。 泛型型別可以是部分型別。 每個部分宣告都必須以相同順序使用相同的參數名稱。
下列關鍵字在部分型別定義中是選擇性項目,但如果出現在某個部分型別定義內,則不可與相同型別的另一個部分定義所指定的關鍵字衝突:
範例 1
描述
在下列範例中,CoOrds 類別的欄位和建構函式 (Constructor) 會宣告於一個部分類別定義中,而其成員 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
範例 2
描述
下列範例顯示您也可以開發部分結構和介面。
程式碼
partial interface ITest
{
void Interface_Test();
}
partial interface ITest
{
void Interface_Test2();
}
partial struct S1
{
void Struct_Test() { }
}
partial struct S1
{
void Struct_Test2() { }
}
部分方法
部分類別或結構可能會包含部分方法。 類別的其中一個部分會包含該方法的簽章。 在相同組件或其他組件中可能會定義選擇性的實作 (Implementation)。 如果沒有提供實作,該方法和該方法的所有呼叫便會在編譯時期移除。
部分方法讓其中一個類別部分的實作器能夠定義類似事件的方法。 其他類別部分的實作器則可判斷是否要實作該方法。 如果沒有實作方法,編譯器 (Compiler) 便會移除方法簽章和該方法的所有呼叫。 方法呼叫,包括任何會因呼叫中對引述的評估而發生的結果,在執行階段皆沒有任何效果。 因此,即使沒有提供實作,在部分類別中的任何程式碼都可以自由使用部分方法。 在方法有進行呼叫但未加以實作的情況下,並不會造成編譯時期或執行階段錯誤。
部分方法特別適合用來自訂產生的程式碼。 它們允許方法名稱和簽章進行保留,以便產生的程式碼可以呼叫該方法,但是開發人員仍可自行決定是否要實作該方法。 就像部分類別,部分方法讓程式碼產生器所產生的程式碼,以及人類開發人員所建立的程式碼能夠一起運作,而不會產生執行階段成本。
部分方法宣告包含了兩個組件:定義和實作。 這些組件可能位於部分類別的個別部分,或是位於相同部分。 如果此時沒有實作宣告,編譯器就會最佳化改變定義宣告和該方法的所有呼叫。
// Definition in file1.cs
partial void onNameChanged();
// Implementation in file2.cs
partial void onNameChanged()
{
// method body
}
部分方法不能是 extern,這是因為主體的存在與否會決定它們要進行定義或是實作。
部分方法可以是泛型的。 條件約束會在定義部分方法宣告時提出,而且可以選擇性地在實作一個宣告時重複。 實作宣告和定義宣告時的參數名稱和型別參數名稱並不一定要完全相同。
您可以將已經定義與實作的部分方法設定為 delegate,但是對於只有經過定義的方法,則無法如此設定。
C# 語言規格
如需詳細資訊,請參閱 C# 語言規格。 語言規格是 C# 語法和用法的決定性來源。