通過分部類型可以定義要拆分到多個文件中的類、結構或接口。
如下:
在 File1.cs 中:
namespace PC { partial class A { int num = 0; void MethodA() { } partial void MethodC(); } }
在 File2.cs 中,聲明:
namespace PC { partial class A { void MethodB() { } partial void MethodC() { } } }
在處理大型項目或自動生成的代碼(如 Windows 窗體設計器提供的代碼)時,在多個文件間拆分類、結構或接口類型可能會非常有用。 分部類型可以包含分部方法。
partial(方法)(C# 參考)
分部方法在分部類型的一個部分中定義它的簽名,並在該類型的另外一個部分中定義它的實現。 類設計人員可以使用分部方法提供由開發人員決定是否實現的方法掛鈎(類似於事件處理程序)。 如果開發人員沒有提供實現,則編譯器會在編譯時移除簽名。 下列條件適用於分部方法:
-
分部類型的兩個部分中的簽名必須匹配。
-
方法必須返回 void。
-
沒有允許的訪問修飾符。 分部方法是隱式私有的。
下面的示例演示在分部類的兩個部分中定義的分部方法:
namespace PM { partial class A { partial void OnSomethingHappened(string s); } // This part can be in a separate file. partial class A { // Comment out this method and the program // will still compile. partial void OnSomethingHappened(String s) { Console.WriteLine("Something happened: {0}", s); } } }
分部類和方法(C# 編程指南)
可以將類或結構、接口或方法的定義拆分到兩個或更多個源文件中。 每個源文件包含類型或方法定義的一部分,編譯應用程序時將把所有部分組合起來。
分部類
在以下幾種情況下需要拆分類定義:
-
處理大型項目時,使一個類分布於多個獨立文件中可以讓多位程序員同時對該類進行處理。
-
使用自動生成的源時,無需重新創建源文件便可將代碼添加到類中。 Visual Studio 在創建 Windows 窗體、Web 服務包裝器代碼等時都使用此方法。 無需修改 Visual Studio 創建的文件,就可創建使用這些類的代碼。
-
若要拆分類定義,請使用 partial 關鍵字修飾符,如下所示:
public partial class Employee { public void DoWork() { } } public partial class Employee { public void GoToLunch() { } }
partial
關鍵字指示可在命名空間中定義該類、結構或接口的其他部分。 所有部分都必須使用 partial
關鍵字。 在編譯時,各個部分都必須可用來形成最終的類型。 各個部分必須具有相同的可訪問性,如 public
、private
等。
如果將任意部分聲明為抽象的,則整個類型都被視為抽象的。 如果將任意部分聲明為密封的,則整個類型都被視為密封的。 如果任意部分聲明基類型,則整個類型都將繼承該類。
指定基類的所有部分必須一致,但忽略基類的部分仍繼承該基類型。 各個部分可以指定不同的基接口,最終類型將實現所有分部聲明所列出的全部接口。 在某一分部定義中聲明的任何類、結構或接口成員可供所有其他部分使用。 最終類型是所有部分在編譯時的組合。
注意: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 注釋
-
接口
-
泛型類型參數屬性
-
class 特性
-
成員
以下面的聲明為例:
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
修飾符只能出現在緊靠關鍵字 class
、struct
或 interface
前面的位置。
分部類型定義中允許使用嵌套的分部類型,如下面的示例中所示:
partial class ClassWithNestedClass { partial class NestedClass { } } partial class ClassWithNestedClass { partial class NestedClass { } }
要成為同一類型的各個部分的所有分部類型定義都必須在同一程序集和同一模塊(.exe 或 .dll 文件)中進行定義。 分部定義不能跨越多個模塊。
類名和泛型類型參數在所有的分部類型定義中都必須匹配。 泛型類型可以是分部的。 每個分部聲明都必須以相同的順序使用相同的參數名。
下面用於分部類型定義中的關鍵字是可選的,但是如果某關鍵字出現在一個分部類型定義中,則該關鍵字不能與在同一類型的其他分部定義中指定的關鍵字沖突:
-
公用
-
專用
-
受保護
-
內部
-
abstract
-
sealed
-
基類
-
new 修飾符(嵌套部分)
-
泛型約束
示例 1
描述
下面的示例在一個分部類定義中聲明 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
示例 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() { } }
分部方法
分部類或結構可以包含分部方法。 類的一個部分包含方法的簽名。 可以在同一部分或另一個部分中定義可選實現。 如果未提供該實現,則會在編譯時刪除方法以及對方法的所有調用。
分部方法使類的某個部分的實施者能夠定義方法(類似於事件)。 類的另一部分的實施者可以決定是否實現該方法。 如果未實現該方法,編譯器會刪除方法簽名以及對該方法的所有調用。 調用該方法(包括調用中的任何參數計算結果)在運行時沒有任何影響。 因此,分部類中的任何代碼都可以隨意地使用分部方法,即使未提供實現也是如此。 調用但不實現該方法不會導致編譯時錯誤或運行時錯誤。
在自定義生成的代碼時,分部方法特別有用。 這些方法允許保留方法名稱和簽名,因此生成的代碼可以調用方法,而開發人員可以決定是否實現方法。 與分部類非常類似,分部方法使代碼生成器創建的代碼和開發人員創建的代碼能夠協同工作,而不會產生運行時開銷。
分部方法聲明由兩個部分組成:定義和實現。 它們可以位於分部類的不同部分中,也可以位於同一部分中。 如果不存在實現聲明,則編譯器會優化定義聲明和對方法的所有調用。
// Definition in file1.cs partial void onNameChanged(); // Implementation in file2.cs partial void onNameChanged() { // method body }
-
分部方法聲明必須以上下文關鍵字 partial 開頭,並且方法必須返回 void。
-
分部方法可以有 ref 參數,但不能有 out 參數。
-
分部方法為隱式 private 方法,因此不能為 virtual 方法。
-
分部方法不能為 extern 方法,因為主體的存在確定了方法是在定義還是在實現。
-
分部方法可以有 static 和 unsafe 修飾符。
-
分部方法可以是泛型的。 約束將放在定義分部方法聲明上,但也可以選擇重復放在實現聲明上。 參數和類型參數名稱在實現聲明和定義聲明中不必相同。
-
你可以為已定義並實現的分部方法生成委托,但不能為已經定義但未實現的分部方法生成委托。