VB.NET 结构(Structure)和类(Class)的区别
类是我们用来构造 VB.NET 应用程序时的最基本的编程结构了。
那结构与类有什么相似之处与不同之处呢?
结构和类,
相同之处是都含有成员,包括构造函数、方法、属性、字段、常量、枚举和事件,都可以实现接口,都有共享的构造函数,都能对成员进行封装。
没错都有构造函数,那结构的构造函数是什么,结构难道也可被实例化成对象?
看这一段代码:
Module Module1
Private Structure structureA
Dim Name As String
Dim Age As Integer Public Sub New(ByVal _Name As String, ByVal _Age As Integer)
Name = _Name
Age = _Age
End Sub
End Structure Sub Main()
Dim intA As New structureA '无参数的构造函数
Dim intB As New structureA("小明", 17) '有参数的构造函数
End Sub
End Module
怎么样,是不是很好奇,明明只定义一个带参数的构造函数,intB 的实例化我们可以明白,但是是 intA 怎么也能通过编译器检测,给实例化呢?
是不是很好奇,结构怎么也能实例化成对象,和类很象呢!
原因是,每个结构都隐式地具有 Public 无参数实例构造函数也就是 Public Sub New(),该构造函数能产生结构的默认值。所以你平时不写构造函数,也一样可以 New出一个结构来。
事实上,我们在结构类型声明中不能声明无参数的构造函数,只能声明“带参数”的构造函数。都可以用 new 来实例化。
那结构和类在内存分配上难道也是 一样的吗?当然不一样,差别可就大了。
简单来说 ,结构是值类型,而类是引用类型。因此,结构使用堆栈分配,类使用堆(托管堆)分配。
示例:
Module Module1
Private Structure structureA
Dim Name As String
Dim Age As Integer
Public Sub New(ByVal _Name As String, ByVal _Age As Integer)
Name = _Name
Age = _Age
End Sub
End Structure Private Class classA
Public sdNumber As Integer = 0
End Class Sub Main()
Dim stcA As New structureA("小明", 0) '有参数的构造函数
Dim stcB As structureA = stcA
stcB.Age = 17
Dim clsA As New classA
Dim clsB As classA = clsA
clsB.sdNumber = 1001
Console.WriteLine("stcA.Age = {0} ,stcB.Age = {1} ", stcA.Age, stcB.Age)
Console.WriteLine("clsA .sdNumber = {0} ,clsB .sdNumber = {1}", clsA.sdNumber, clsB.sdNumber)
Console.Read()
End Sub
End Module
结果如图:
这就是值类型和引用类型的差别。
结构的实例 stcB.Age 赋值并不影响stcA.Age, 这是因为虽然它们同属于一种SHenry结构,而结构也是属于值类型的,值类型的变量存储在堆栈上的,每个变量都有自己单独的内存空间,所以互不影响。
相反,给 clsB.sdNumber 赋值 17 后; 则会影响slcA.sdNumber 变量的值,这是因为在 Classs 类中,虽然 sdNumber 变量是值类型,但它的对象是类,类是引用类型,而引用类型是存储在堆(托管堆)上,堆上存储的是对象的实际对象值。
不管后面定义多少个 class 类型的变量,只要不实例化,它们都只是在堆栈上划分各自的空间,来存储 class 对象的引用地址,而这每个不同名称的引用地址都指向同一个引用对象的实际值。所以,不管哪个 class 类型变量改变了值,它都会影响原始值。
说得更清楚一点,类作为引用类型,是存储在堆上,只能通过引用地址来访问它们,不能直接访问。
引用类型的变量总是包含该类型的值引用,或包含空引用。空引用不引用任何内容;除分配空引用外,对空引用进行的任何操作都是无效的。
引用类型的变量赋值只会创建引用的一个副本,而不是所引用的值的副本。它们实际上都是会指向同一块存储区的。
结构是直接存储在堆栈上,要么在数组中,要么在另一个类型中 。当包含结构实例的位置被销毁时,结构实例也会被销毁。值类型总是可以直接 访问。我们不能创建对值类型的引用,也不能引用已销毁的值类型实例。值类型的变量总是包含此类型的值。与引用类型不同,值类型的值不能为空引用,也不能引用派生相近程度较大的类型的对象。值类型的变量赋值会创建所赋的值的副 本,当然会新开辟一块内存区来保存值。
那它们还有什么区别没有呢?
当然有很多,比如所有的结构成员都默认为 Public,而类的变量和常量默认为 Private。其他的类成员默认为 Public;结构成员不能声明为 Protected,而类成员可以;结构过程不能处理事件,类过程可以;结构变量声明不能指定初始值、New 关键字或数组初始大小,类变量声明可以。
结构从不终止,所以公共语言运行库从不在任何结构上调用 Finalize 方法;类可由垃圾回收器终止,垃圾回收器会跟踪未完成的引用直到某个特定的实例,当检测到没有剩下的活动引用时, 垃圾回收器将在类上调用 Finalize。”
因为结构是值类型,是由系统统一管理内存,不是引用,所以不会对内存造成危害。
还有结构是不可继承的,而类可以继承。其实结构自身是从 ValueType 类隐式继承下来的。
数据类型可分为值类型和引用类型。值类型要么是堆栈分配的,要么是在结构中以内联方式分配的。引用类型是堆分配的,引用类型和值类型都是从最终的基类 Object 派生出来的。当值类型需要充当对象时 ,就在堆上分配一个包装,该包装能使值类型看上去像引用对象一样,并且将该值类型的值复制给它。该包装被加上标记,以便系统知道它包含一个值类型。这个过程程称为装箱,其反向过程程称为拆箱。装箱和拆箱能够使任何类型像对象一样进行处理。
VB.NET 结构(Structure)和类(Class)的区别的更多相关文章
- C++中 结构体和类的异同
在C++中,结构体是一种特殊形态的类. 结构体和类的唯一区别就是: 结构体和类具有不同的默认访问控制属性. 类中,对于未指定访问控制属性的成员,其访问控制属性为私有类型(private) 结构体中, ...
- 介绍C#结构体与类区别
1. 结构体与类定义方式 结构体定义使用struct类定义使用class 结构体: struct testDemo{ int num; void action(){ } } 类: class test ...
- Swift结构体和类
Swift结构体 在Swift标准中,绝大多数的公开的类型都是结构体,而枚举和类只占很小的一部分 比如Bool.Int.Double.String.Array.Dictionary等常见的类型都是结构 ...
- c#中结构体(struct)和类(class)的区别
一.类与结构的示例比较: 结构示例: public struct Person { string Name; int height; int weight public bool overWeight ...
- C#中结构体和类的区别
结构体和类同样能够定义字段,方法和构造函数,都能实例化对象,这样看来结构体和类的功能好像是一样的了,但是他们在数据的存储上是不一样的 C#结构体和类的区别问题:这两种数据类型的本质区别主要是各自指向的 ...
- C#中的结构体与类的区别
经常听到有朋友在讨论C#中的结构与类有什么区别.正好这几日闲来无事,自己总结一下,希望大家指点. 1. 首先是语法定义上的区别啦,这个就不用多说了.定义类使用关键字class 定义结构使用关键字str ...
- 转载 C#结构体(struct)和类(class)的区别
转载原地址: http://dotnet.9sssd.com/csbase/art/8 C#结构体和类的区别问题:在C#编程语言中,类属于引用类型的数据类型,结构体属于值类型的数据类型,这两种数据类型 ...
- Swift结构体与类
在面向过程的编程语言(如C语言)中,结构体用得比较多,但是面向对象之后,如在C++和Objective-C中,结构体已经很少使用了.这是因为结构体能够做的事情,类完全可以取而代之.而Swift语言却非 ...
- C++中结构体与类的区别(结构不能被继承,默认是public,在堆栈中创建,是值类型,而类是引用类型)good
结构是一种用关键字struct声明的自定义数据类型.与类相似,也可以包含构造函数,常数,字段,方法,属性,索引器,运算符和嵌套类型等,不过,结构是值类型. 1.结构的构造函数和类的构造函数不同. a. ...
- C C++ 中结构体与类
先来说说C和C++中结构体的不同 a) C语言中的结构体不能为空,否则会报错 1>d:\myproject\visual studio 2013\projects\myc++\main.c(71 ...
随机推荐
- 【Python学习】由于windows环境问题导致的不能安装某些需要VC编译的插件
由于windows环境问题导致的不能安装某些需要VC编译的插件 下载地址:http://www.lfd.uci.edu/~gohlke/pythonlibs/ 安装方法: 在CMD中输入 pip in ...
- 蜘蛛牌(hdu 1584 DFS)
蜘蛛牌 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- 移动端Web App自适应布局探索
1.困扰多时的问题 在这之前做Web App开发的的时候,在自适应方面一般都是宽度通过百分比,高度以iPhone6跟iPhone5之间的一个平衡值写死,我们的设计稿都是iPhone5的640 * 11 ...
- Ubuntu14.04安装PostpreSQL9.3.5记录
安装参考:http://www.postgresql.org/download/linux/ubuntu/ y@y:~$ sudo apt-get install postgresql-9.3 pos ...
- USB系列之五:用汇编实现的一些USB功能
前面的USB系列一至四,实现了我们需要的一些USB功能,但都是用C语言的32位代码,之后我们插进了三篇关于DOS下设备驱动程序的文章,我们现在应该清楚,当我们要在DOS下写一个U盘的驱动时,最好使用汇 ...
- C# Process类_进程管理器Demo
Process用于管理计算机的进程,下面给出一个C#进程管理器的DEMO. namespace ProcessManager { public partial class Form1 : Form { ...
- cf479A Expression
A. Expression time limit per test 1 second memory limit per test 256 megabytes input standard input ...
- Mod_Python中文文档
Mod_Python中文文档 mod_python中文文档
- 把程序嵌入网页之ATL编写ActiveX[标准窗口+接受参数]
从VS2010开始ATL ActiveX支持IObjectSafety接口,所以用VS2010来编写,新建一个ATL项目 向导的第一页没什么东西,直接下一步,选项可以根据具体需求调整 点“完成”,切换 ...
- js跳转页面代码用法
一:window.location.href='https://www.baidu.com'; 需要加上http或者https,否则会查找项目内htm打开. 二:window.history.bac ...