首页 > 代码库 > 分部类和分部方法

分部类和分部方法

分部类通过关键字partial进行声明,分部类可以将类、结构或接口的定义拆分到两个或多个源文件中。每个源文件包含类定义的一部分,编译应用程序时将把所有部分组合起来。在以下几种情况下需要拆分类定义:

  • 处理大型项目时,使一个类分布于多个独立文件中可以让多位程序员同时对该类进行处理。
  • 使用自动生成的源时,无需重新创建源文件便可将代码添加到类中。Visual Studio 在创建 Windows 窗体、Web 服务包装代码等时都使用此方法。您无需编辑 Visual Studio 所创建的文件,便可创建使用这些类的代码。

定义分部类,如下所示:

 1 public partial class Employee
 2 {
 3     public void DoWork()
 4     {
 5     }
 6 }
 7 
 8 public partial class Employee
 9 {
10     public void GoToLunch()
11     {
12     }
13 }
上边的代码等价于:
1 public partial class Employee
2 {
3     public void DoWork()
4     {
5     }
6    public void GoToLunch()
7    {
8    }
9 }

 

使用 partial 关键字表明可在命名空间内定义该类、结构或接口的其他部分。所有部分都必须使用 partial 关键字。在编译时,各个部分都必须可用来形成最终的类型。各个部分必须具有相同的可访问性,如 public、private 等。
 

如果将任意部分声明为抽象的,则整个类型都被视为抽象的。如果将任意部分声明为密封的,则整个类型都被视为密封的。如果将任意部分声明为基类型,则整个类型都将继承该类。

 

指定基类的所有部分必须一致,但忽略基类的部分仍继承该基类型。各个部分可以指定不同的基接口,最终类型将实现所有分部声明所列出的全部接口。在某一分部定义中声明的任何类、结构或接口成员可供所有其他部分使用。最终类型是所有部分在编译时的组合。

 

嵌套类型可以是分部的,即使它们所嵌套于的类型本身并不是分部的也如此。例如:

 1 class Container
 2 {
 3     partial class Nested
 4     {
 5         void Test() { }
 6     }
 7     partial class Nested
 8     {
 9         void Test2() { }
10     }
11 }

编译时将对分部类型定义的属性进行合并。例如,下面的声明:

1 [System.SerializableAttribute]
2 partial class Moon { }
3 
4 [System.ObsoleteAttribute]
5 partial class Moon { }

等效于:

1 [System.SerializableAttribute]
2 [System.ObsoleteAttribute]
3 class Moon { }

所部类在编译时会将所有分部类类中定义的以下内容进行合并:

  • XML 注释

  • interfaces

  • 泛型类型参数属性

  • 类属性

  • 成员

例如,下面的声明:

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

等效于:

1 class Earth : Planet, IRotate, IRevolve { }

注意:

  • 分部修饰符不可用于委托或枚举声明中。
  • 要作为同一类型的各个部分的所有分部类型定义都必须使用 partial 进行修饰。例如,下面的类声明将生成错误:

1 public partial class A { }
2 //public class A { }  // Error, must also be marked partial
  • partial 修饰符只能出现在紧靠关键字 classstruct 或 interface 前面的位置。

  • 分部类型定义中允许使用嵌套的分部类型,例如:

1 partial class ClassWithNestedClass
2 {
3     partial class NestedClass { }
4 }
5 
6 partial class ClassWithNestedClass
7 {
8     partial class NestedClass { }
9 }
  • 要成为同一类型的各个部分的所有分部类型定义都必须在同一程序集和同一模块(.exe 或 .dll 文件)中进行定义。分部定义不能跨越多个模块。

  • 类名和泛型类型参数在所有的分部类型定义中都必须匹配。泛型类型可以是分部的。每个分部声明都必须以相同的顺序使用相同的参数名。

  • 下面的用于分部类型定义中的关键字是可选的,但是如果某关键字出现在一个分部类型定义中,则该关键字不能与在同一类型的其他分部定义中指定的关键字冲突:
    • public
    • private
    • protected
    • internal
    • abstract
    • sealed
    • 基类
    • new 修饰符(嵌套部分)
    • 一般约束
下面的示例在一个分部类定义中声明类 CoOrds 的字段和构造函数,在另一个分部类定义中声明成员 PrintCoOrds
 1 public partial class CoOrds
 2 {
 3     private int x;
 4     private int y;
 5 
 6     public CoOrds(int x, int y)
 7     {
 8         this.x = x;
 9         this.y = y;
10     }
11 }
12 
13 public partial class CoOrds
14 {
15     public void PrintCoOrds()
16     {
17         System.Console.WriteLine("CoOrds: {0},{1}", x, y);
18     }
19 
20 }
21 
22 class TestCoOrds
23 {
24     static void Main()
25     {
26         CoOrds myCoOrds = new CoOrds(10, 15);
27         myCoOrds.PrintCoOrds();
28     }
29 }
输出
CoOrds: 10,15
从下面的示例可以看出,您也可以开发分部结构和接口。
 1 partial interface ITest
 2 {
 3     void Interface_Test();
 4 }
 5 
 6 partial interface ITest
 7 {
 8     void Interface_Test2();
 9 }
10 
11 partial struct S1
12 {
13     void Struct_Test() { }
14 }
15 
16 partial struct S1
17 {
18     void Struct_Test2() { }
19 }

 分部方法

  • 分部方法只可以定义在分部类中
  • 分部方法返回值必须为void
  • 分部方法可以有参数(包含被this、ref或params修饰的参数,但不能有out修饰符)
  • 分布方法不能具有访问修饰符或virtual、abstract、override、new、sealed或者extern修饰符
  • 当分部方法没有实现代码时,C#编译器会在编译时删除其调用语句。

例如:

 1     static partial class CarProperty
 2     {
 3         public static bool Move(int s)
 4         {
 5             Accelerate(s);
 6             return true;
 7         }
 8         static partial void Accelerate(int s);
 9     }
10     static partial class CarProperty
11     {
12         static partial void Accelerate(int s)
13         {
14             MessageBox.Show(s.ToString() + "已加速!");
15         }
16     }

 

分部类和分部方法