匿名类型&&堆和栈
2017-09-23 15:56
204 查看
匿名类型
在前面的代码中,我们创建变量(对象)的时候,都指定了变量的类型,但是我们也可以不去指定类型,这个就叫做匿名类型。我们可以使用var声明一个匿名类型,匿名类型初始化的时候,这个变量的类型就被确定下来了,并且之后不能够在被修改。
static void Main(string[] args) { int i = 100; var j = 1000; j = 98; j = "sdwd"; //j的类型已经被确定为int类型,不能够被修改了 var a = "asdwd"; var v1 = new Vector3(); }
在这段代码中我们可以看到j被确定为int类型之后不能够再被定义为string类型了。
堆和栈
堆和栈是程序运行时的内存区域,我们把内存分为堆空间和栈空间。栈空间:空间较小但是读取速度快,数据只能从栈的顶端插入和删除,把数据放入栈顶称为入栈(push),从栈顶删除数据称为出栈(pop)。
堆空间:空间较大但是读取速度慢。与栈不同,堆空间的内存能够以任意顺序存入和溢出。
讲到程序运行的内存区域,就要谈到内存的回收。C语言里的内存管理可以由自己来完成,但是C#里面内存管理我们可以不用去关心,因为CLR(公共语言运行库)里的内存管理机制会自动帮我们回收无用的内存。(CLR在第一篇文章有大概的描述。)
内存管理机制又被称作GC(垃圾回收器),在堆空间中,一旦有对象不再被程序使用,垃圾回收器发现无主对象,就会释放该对象,释放之后,该对象占据的内存空间就可以重新被使用了。
值类型和引用类型
既然有堆和栈两种内存区域,那我们定义的变量是应该放在哪种区域呢?不同类型存放的区域是不一样的。值类型:存放在栈空间(包括整数,bool,struct,char,小数这几种类型)。值类型只需要一段单独的内存用于存储实际的数据。
引用类型:存放在堆空间(包括string,数组,自定义的类,内置的类)。
引用类型需要两段内存:第一段存储实际的数据,这段内存总是位于堆中;第二段是一个引用,存放着内存地址,指向数据在堆中的存放位置,该引用位于栈中。
内存分析
当一个方法中同时有值类型和引用类型,在程序结束之后,GC会先释放一个在栈中的内存空间,然后检查堆空间有没有无主对象,有的话就释放该对象占据的空间,没有的话就释放栈的内存空间,循环往复。
当一个引用类型赋值给另一个引用类型的时候,并不是修改堆空间内的数值,而是修改栈空间的里的内存地址。
static void Test3() { string name = "lymon"; string name2 = "baidu"; name = name2; Console.WriteLine(name + name2); }
在这段代码中,name2赋值给name,实质上,name指向的是“lymon”这段数据,当赋值之后,name就指向了“baidu”这段数据,而“lymon”这段数据没有被修改,只是没有被栈空间里的数据引用了。
和上面的情况一样,一个引用类型赋值给另一个引用类型,那么当内村回收之后,堆空间只剩下一块内存空间,被赋值的引用类型的堆内存消失,这时候两个引用类型都指向同一段数据,无论怎么修改,都是修改同一块内存空间。
static void Test4() { Vector3 v = new Vector3(); v.x = 100; v.y = 100; v.z = 100; Vector3 v2 = new Vector3(); v2.x = 200; v2.y = 200; v2.z = 200; v2 = v; v2.x = 300; Console.WriteLine(v.x); }
Vector3是只定义了x,y,z的类。当v赋值给v2时,v2指向的堆内存的数据就消失了,这时v和v2指向的都是v的数据,所以当v2.x=300的时候,v.x的值也为300。
还有一种更复杂的情况,就是引用类型的嵌套。
例如在数组中,存储的是值类型的数据,那么在数组中直接存储值;但是数组里要是存储的是引用类型的数据,那么数组中存储的就是内存地址了,然后内存地址再去指向数值。
static void Test5() { Vector3[] vArray = new Vector3[] { new Vector3(), new Vector3(), new Vector3() }; Vector3 v1 = vArray[0]; vArray[0].x = 100; v1.x = 200; Console.WriteLine(vArray[0].x); }
在这个例子中,vArray数组中存的是三个引用类型,vArray在栈中存储了一个内存地址,指向堆空间的一段数据,该数据又存储了三个内存地址,分别指向xyz数值。
整个程序的内存关系大概就是这个样子。
相关文章推荐
- C#==>匿名类型
- VHDL数据类型 &自定义数据类型
- 深入讲解C#编程中嵌套类型和匿名类型的定义与使用
- <细节>C++标准库string类型
- 深入C#内存管理来分析值类型&引用类型,装箱&拆箱,堆栈几个概念组合之间的区别
- mysql(一)语言&列类型
- C# 匿名类型和初始化器
- 探讨:php中在foreach中使用foreach ($arr as &$value) 这种类型的解释
- 怎么去掉Xcode工程中的某种类型的警告 Implicit conversion loses integer precision: 'NSInteger' (aka 'long') to 'int32
- java :引用类型的转换  方法重载和重写  构造函数 修饰符
- mybatis在<if>中传入一个简单类型参数的两种写法。
- <PY><core python programming笔记>C7 字典和集合类型
- Oracle&nbsp;date类型数据
- Visual C# 2008+SQL Server 2005 数据库与网络开发――3.2.4 匿名类型
- DataGridView中的列类型设置为Combo,模式为可以选择&可以输入,解决方法。
- VS2010包含windows.h时winsock2.h出现"fd_set":struct类型重定义
- iOS 判断设备类型
- java基本数据类型&&int与Integer区别
- 机房收费系统之数据类型&除法运算符
- c++基本类型&&&c++string与c风格字符串的相互转化