C#学习笔记——结构与类
来源:互联网 发布:天敏网络机顶盒 编辑:程序博客网 时间:2024/06/02 07:33
1. 值类型和引用类型
在C#中有大量的值类型, int,char,float…等C#的预定义的基本类型都是值类型,这里面string是一个例外。值类型直接包含值,变量引用的位置就是值在内存中实际存储的位置,存储在称为栈的内存区域内。引用类型和引用它们的变量指向数据存储位置。引用类型并不直接存储值,它们存储的是对一个内存位置的引用(内存地址),要去那个位置才能找到真正的数据。引用类型指向的内存区域称为堆。
我们需要使用自定义的类型时,自定义的引用类型很常用,就是我们常用的“类”。在这里要提一下自定义的值类型,一种是“结构”,另外一种是“枚举”。• C++中的结构是多余的东西,仅仅为了兼容C而存在。C#中的结构与类有许多实质的区别,结构是轻量级的自定义数据类型,其数据存储于栈中。
2. 结构和类的区别
比较项目
struct
class
1. 存储位置
栈
托管堆
2. 变量赋值为null
不能
可以
3. 继承与派生
不支持
支持
4. 定义无参构造函数
不能
能
5. 构造函数初始化所有字段
必须
不必
6. 用new来实例化一个对象
不一定
必须
7. 定义析构函数
不能
能
8. 对象复制
正本与副本无关
浅拷贝和深拷贝
9. 如何回收
无需回收
自动回收机制
10. 参数传送
按值传送
按地址传送
11. 使用初始化表
不能
可以
12. 作为List元素能否修改
不能
可以
C++中,结构和类几乎是同义词,区别只在于:结构的成员默认为公开的,类的成员默认为私有的。但是在C#中,结构和类的成员默认都是私有的。
下面用一个代码实例说明一下上述区别的表现,代码选自《C#本质论4.0》,代码清单8-1:
using System;using System.Diagnostics;using System.ComponentModel;using System.Text;using System.Collections.Generic;namespace MyProcessSample{ struct Angle { //4.结构不能定义无参构造函数,所以以下的定义是错误的 //public Angle() { }//Error //5.构造函数初始化所有字段,如下面的初始化必须包括全部三个字段 public Angle(int hours, int minutes, int seconds) { _Hours = hours; _Minutes = minutes; _Seconds = seconds; } public int Hours { get { return _Hours; } } public int _Hours; public int Minutes { get { return _Minutes; } } private int _Minutes; public int Seconds { get { return _Seconds; } } private int _Seconds; public Angle Move(int hours, int minutes, int seconds) { return new Angle( Hours + hours, Minutes + minutes, Seconds + seconds); } } // Declaring a class - a reference type // (declaring it as a struct would create a value type // larger than 16 bytes.) class Coordinate { //4.定义无参构造函数在类中是允许的,如下 public Coordinate() { } public Angle Longitude { get { return _Longitude; } set { _Longitude = value; } } private Angle _Longitude; public Angle Latitude { get { return _Latitude; } set { _Latitude = value; } } private Angle _Latitude; } class MyProcess { static void Main(string[] args) { //4.定义无参构造函数,在这里可以调用无参的构造函数,而且下面的输出为0,为什么?? Angle ag = new Angle(); Console.WriteLine(ag.Minutes); //2.变量赋值为null 如下的代码说明struct不能直接赋值为null //ag = null;//Error //而可以使用下面的方式来声明 Angle? agg = null; if (agg.HasValue) Console.WriteLine("Has value"); else Console.WriteLine("=NULL"); //6.用new来实例化一个对象 //struct可以不使用new来初始化,如ag3,并且可以对公有成员初始化,当然这样会引起数据的不安全 Angle ag2 = new Angle(10, 5, 2); Angle ag3; ag3._Hours = 9; //class不可以,如cd2这样的形式初始化就会报错 Coordinate cd1 = new Coordinate(); cd1.Longitude = ag2; Coordinate cd2; //cd2.Longitude = ag2;//Error Coordinate cd3 = new Coordinate { Latitude = ag2, Longitude = ag }; Angle ag4 = new Angle { _Hours = 5 };//这里说明struct也是可以使用初始化列表的,前提是这个字段是公有的 Angle ag5 = new Angle(7, 3, 1); Angle ag6 = new Angle(9, 9, 9); List<Angle> allAgs = new List<Angle>() { ag, ag2, ag4 }; Console.WriteLine(allAgs[0].Hours + "," + allAgs[1].Hours + "," + allAgs[2].Hours); allAgs[0] = allAgs[1]; Console.WriteLine(allAgs[0].Hours + "," + allAgs[1].Hours + "," + allAgs[2].Hours); allAgs[0] = ag5; Console.WriteLine(allAgs[0].Hours + "," + allAgs[1].Hours + "," + allAgs[2].Hours); Coordinate cd5 = new Coordinate { Latitude = ag5,Longitude=ag6 }; List<Coordinate> allCds = new List<Coordinate>() { cd1, cd3 }; Console.WriteLine(allCds[0].Latitude.Minutes + "," + allCds[1].Latitude.Minutes); allCds[0] = allCds[1]; Console.WriteLine(allCds[0].Latitude.Minutes + "," + allCds[1].Latitude.Minutes); allCds[0] = cd5; Console.WriteLine(allCds[0].Latitude.Minutes + "," + allCds[1].Latitude.Minutes); //以下说明引用类型的赋值存在深拷贝,浅拷贝的问题,直接赋值相当于浅拷贝 Coordinate cd6 = cd5; Console.WriteLine(cd6.Longitude.Hours + "," + cd5.Longitude.Hours); cd6.Longitude = new Angle(999, 999, 999); Console.WriteLine(cd6.Longitude.Hours + "," + cd5.Longitude.Hours); } }}对第8条,对象的复制方式,struct的形式完全和常用值类型一样,但是class的复制就涉及到深拷贝和浅拷贝,可具体参考本站其它博文(http://blog.csdn.net/shaopengfei/article/details/39376441)。
第11条,第12条来自陈老师的讲课资料,不过现在验证来好象有点出入,比如第11条,如果struct里有一个公有的字段,那么是可以使用初始化列表初始化的。第12条也是,当时陈老师是这么讲解的:
List<T>中,元素只能用索引器来获取,例如 a[i]。索引器返回的本是可读可写的元素,但struct元素是按值传送的,修改返回值对于List中的元素毫无影响。例如,a[i] = a[j]; C#此时发出编译错误,实在是提醒程序员别误入陷阱。但元素如果是class的,返回值则是按地址传送的,是一个引用,修改其值就是修改List中的元素, a[i] = a[j]; 是允许的。
经过验证,见上述代码的第109-122行,这些都是可以实现的。或者我对这一段理解有问题,还有待于深入的探讨。
3. 结构适合的场合
struct 类型适于表示 Point、Rectangle 和 Color 等轻量对象。 尽管使用自动实现的属性将一个点表示为类同样方便,但在某些情况下使用结构更加有效。 例如,如果声明一个 1000 个 Point 对象组成的数组,为了引用每个对象,则需分配更多内存;这种情况下,使用结构可以节约资源。 因为 .NET Framework 包含一个名为 Point 的对象,所以本示例中的结构命名为“CoOrds”。
public struct CoOrds{ public int x, y; public CoOrds(int p1, int p2) { x = p1; y = p2; }}将较小的类声明为结构,可以提高系统的处理效率。
- C#学习笔记——类与结构
- C#学习笔记——类与结构
- C#学习笔记——结构与类
- C#学习笔记——结构体
- C#学习笔记——类和结构
- C#学习笔记(一)——C#核心编程结构 I Main、Console、基本数据类型与循环
- C#学习笔记之——枚举、结构体
- C# Hadoop学习笔记(三)—集群部署结构
- C#学习笔记类和结构体
- C#学习笔记 结构介绍
- 黑马程序员之C#学习笔记:类与结构的区别
- C#学习笔记6——C#中枚举、结构、数组
- swift学习笔记8 类与结构
- C#学习笔记16-结构体和类
- C#2005 .NET3.0高级编程学习笔记————结构,部分类,静态类,Object类
- C#学习笔记5——operator、explicit与implicit
- C#学习笔记——新语法与语法糖
- C#学习笔记—值类型与引用类型
- 摄像机和镜头的基础知识
- Qt数据库之数据库连接池
- Mac 可设置环境变量的位置、查看和添加PATH环境变量
- UGUI实现Joystick
- ASP.NET MVC Model Binding(模型绑定)
- C#学习笔记——结构与类
- Swift开发之自动布局
- 第二章
- process.waitFor() 返回值含义
- 模块(module)方式创建maven工程
- Qt数据库之数据库访问工具 DBUtil
- hadoop集群搭建文章
- spring quartz配置文件
- 类的图解