­

C#2.0新增功能01 分部类与分部方法

  • 2019 年 10 月 4 日
  • 笔记

分部类型

  拆分一个、一个结构、一个接口或一个方法的定义到两个或更多的文件中, 每个源文件包含类型或方法定义的一部分,编译应用程序时将把所有部分组合起来。

分部类

在以下几种情况下需要拆分类定义:

  • 处理大型项目时,使一个类分布于多个独立文件中可以让多位程序员同时对该类进行处理。
  • 当使用自动生成的源文件时,你可以添加代码而不需要重新创建源文件。 Visual Studio 在创建Windows 窗体、Web 服务包装器代码等时会使用这种方法。 你可以创建使用这些类的代码,这样就不需要修改由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 注释
  • 接口
  • 泛型类型参数属性
  • class 特性
  • 成员

以下面的声明为例:

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

它们等效于以下声明:

class Earth : Planet, IRotate, IRevolve { }

限制

处理分部类定义时需遵循下面的几个规则:

  • 要作为同一类型的各个部分的所有分部类型定义都必须使用 partial 进行修饰。 例如,下面的类声明会生成错误:
public partial class A { }  //public class A { }  // 错误, 也必须使用 partial 修饰
  • partial 修饰符只能出现在紧靠关键字 classstructinterface 前面的位置。
  • 分部类型定义中允许使用嵌套的分部类型,如下面的示例中所示:
partial class ClassWithNestedClass  {      partial class NestedClass { }  }    partial class ClassWithNestedClass  {      partial class NestedClass { }  }
  • 要成为同一类型的各个部分的所有分部类型定义都必须在同一程序集和同一模块(.exe 或 .dll 文件)中进行定义。 分部定义不能跨越多个模块。
  • 类名和泛型类型参数在所有的分部类型定义中都必须匹配。 泛型类型可以是分部的。 每个分部声明都必须以相同的顺序使用相同的参数名。
  • 下面用于分部类型定义中的关键字是可选的,但是如果某关键字出现在一个分部类型定义中,则该关键字不能与在同一类型的其他分部定义中指定的关键字冲突:

有关详细信息,请参阅类型参数的约束

示例 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();            Console.WriteLine("Press any key to exit.");          Console.ReadKey();      }  }  // 输出: 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() { }  }