结构和类 (Visual Basic)

Visual Basic 统一了结构和类的语法,因此,这两个实体支持大多数相同的功能。 但是,结构和类之间也存在重要差异。

类的优点是引用类型 - 传递引用比传递带有所有数据的结构变量更有效。 另一方面,结构不需要在全局堆上分配内存。

由于你不能从结构继承,因此,结构应仅用于不需要扩展的对象。 当想要创建的对象的实例大小较小时,请使用结构,并考虑类与结构的性能特征。

相似性

结构和类在以下方面类似:

  • 两者都是容器类型,这意味着它们将其他类型作为成员包含在内。

  • 两者都具有成员,其中可以包含构造函数、方法、属性、字段、常数、枚举、事件和事件处理程序。

  • 两者的成员可以具有个性化的访问级别。 例如,一个成员可以声明为 Public,另一个成员可以声明为 Private

  • 两者可以实现接口。

  • 两者都可以具有共享的构造函数(带或不带参数)。

  • 两者都可以公开默认属性,前提是该属性至少采用一个参数。

  • 两者都可以声明和引发事件,并且两者都可以声明委托。

差异

结构和类在以下方面有所不同:

  • 结构是值类型;类是引用类型。 结构类型的变量包含结构的数据,而不是与类类型一样包含对数据的引用。

  • 结构使用堆栈分配;类使用堆分配。

  • 所有结构元素默认是 Public 的;类变量和常量默认是 Private 的,而其他类成员默认是 Public 的。 类成员的这种行为提供与 Visual Basic 6.0 系统默认值的兼容性。

  • 一个结构必须至少有一个非共享变量或非共享的非自定义事件元素;一个类可以完全为空。

  • 结构元素不能声明为 Protected;但类成员可以。

  • 仅当结构过程是共享的Sub 过程时它才可以仅通过 AddHandler 语句的方式处理事件;任何类过程都可以使用 Handles 关键字或 AddHandler 语句处理事件。 有关详细信息,请参阅事件

  • 结构变量声明不能为数组指定初始值设定项或初始大小;但类变量声明可以。

  • 结构隐式继承自 System.ValueType 类并且不能从任何其他类型继承;类可以继承自任何类或除了 System.ValueType 之外的类。

  • 结构不可继承;但类可以。

  • 结构绝不会终止,因此,公共语言运行时 (CLR) 从不对任何结构调用 Finalize 方法;类由垃圾回收器 (GC) 终止,后者在检测到没有剩余的活动引用时对类调用 Finalize

  • 结构不需要构造函数;但类需要。

  • 仅当结构采用参数时才可具有非共享构造函数;但无论带不带参数,类都可以具有非共享构造函数。

每个结构都具有一个不带参数的隐式公共构造函数。 此构造函数将结构的所有数据元素初始化为它们的默认值。 你不能重新定义此行为。

实例和变量

由于结构是值类型,因此每个结构变量将永久绑定到单个结构实例。 但类是引用类型,并且对象变量可在不同时间引用各种类实例。 这一区别会按以下方式影响结构和类的使用:

  • 初始化。 结构变量使用结构的无参数构造函数隐式包含元素的初始化。 因此,Dim s As struct1 等效于 Dim s As struct1 = New struct1()

  • 分配变量。 当你将一个结构变量分配给另一个结构变量或将一个结构实例传递给一个过程参数时,所有变量元素的当前值都会复制到新结构。 当你将一个对象变量分配给另一个对象变量或将一个对象变量传递给一个过程时,只会复制引用指针。

  • 不分配任何内容。 你可以将值 Nothing 赋予给结构变量,但实例会继续与变量关联。 你仍可以调用其方法并访问其数据元素,尽管变量元素是通过赋值重新初始化的。

    与此相反,如果你将一个对象变量设置为 Nothing,你会将它与任何类实例取消关联,并且你无法通过该变量访问任何成员,除非你向它分配了另一个实例。

  • 多个实例。 一个对象变量在不同时间可以有分配给它的不同类实例,而多个对象变量可同时引用相同的类实例。 对类成员的值所做的更改会在通过指向同一实例的另一个变量访问这些成员时影响这些成员。

    但是,结构元素在它们自己的实例中是隔离的。 对它们的值所做的更改不会反映在其他任何结构变量中,即使在同一 Structure 声明的其他实例中也是如此。

  • 相等。 必须使用逐一元素测试来执行两个结构的相等测试。 可以使用 Equals 方法比较两个对象变量。 Equals 指示两个变量是否指向同一个实例。

另请参阅