C#中结构类型和类类型在语法上非常相似,他们都是一种数据结构,都可以包括数据成员和方法成员。

  结构和类的区别:

  1、结构是值类型,它在栈中分配空间;而类是引用类型,它在堆中分配空间,栈中保存的只是引用。

  2、结构类型直接存储成员数据,让其他类的数据位于对中,位于栈中的变量保存的是指向堆中数据对象的引用。

  C#中的简单类型,如int、double、bool等都是结构类型。如果需要的话,甚至可以使用结构类型结合运算符运算重载,再为C#语言创建出一种新的值类型来。

  由于结构是值类型,并且直接存储数据,因此在一个对象的主要成员为数据且数据量不大的情况下,使用结构会带来更好的性能。

一、声明结构的语法 - struct关键字

    public struct AddressBook
{
//字段、属性、方法、事件
}

  对于类而言,两个变量指向同一个对象的情况是存在的,因此对这样两个变量中的任意一个进行操作,起结果必然会影响另外一个,因为它们指向的是同一个对象。

  结构是值类型,,直接包含它自己的数据,每个结构都保存自己的一份数据,修改每一个结构的数据都不会对其他结构的数据造成影响。

二、给结构赋值

  如果从结构中创建一个对象,并将该对象赋给某个变量,则该变量包含结构的全部值。复制类型为结构的变量时,将同时复制该结构所持有的所有数据。由于结构不是引用类型,因此结构类型的变量不能被赋予null值。

public class Program
{
static void Main(string[] args)
{
PersonStruct p1, p2; //与类一样,但可以不new
p1.Name = "张飞";
p1.MobilePhone = "13553663108";
p1.Birthday = DateTime.Now.AddYears(-10); p2 = p1; //将p1的值赋给p2 //由于是值类型,因此赋值等于将全部值全部复制到p2的栈空间
p2.Name = "关羽"; //然后修改p2的值看是否会影响p1
Console.WriteLine(p1.Name); //输出 张飞 没影响 PersonClass p3 = new PersonClass();
p3.Name = "张飞";
p3.MobilePhone = "13553663108";
p3.Birthday = DateTime.Now.AddYears(-10); PersonClass p4 = new PersonClass();
p4 = p3; //将p3的值赋给p4 赋值后,由于是引用类型,因此两个对象指向的是同一个地址(堆空间)
p4.Name = "关羽"; //然后修改p4的值看是否会影响p3
Console.WriteLine(p3.Name); //输出 关羽 有影响 Console.ReadKey();
}
} public class PersonClass
{
public string Name;
public string MobilePhone;
public DateTime Birthday;
} public struct PersonStruct
{
public string Name;
public string MobilePhone;
public DateTime Birthday;
}

  将一个结构变量赋值给另一个结构变量,就是把数据从一个结构复制到另一个结构。而类则不同,在类的变量之间,复制的是引用,而不是类数据。。因此当数据比较大的时候,这种数据复制机制会带来较大的开销。

三、构造函数

  结构类型可以有实例构造函数和静态构造函数,但不能有析构函数。

  1、实例构造函数

  结构类型都有一个预定义的,没有参数的构造函数,这点与类是一样的。此构造函数不允许删除和重定义,并且这个无参数的构造函数会一直存在,并不会因为定义了其他带参数的构造函数就消失,这一点和类不同。

  注意如果没有使用new运算符,是不可以使用数据成员的值(除非已显示地设置了该数据成员的值)和调用函数成员的(除非所有数据成员均已经被赋值)。

四、静态构造函数

  和类一样,结构类型也可以有静态构造函数,静态构造函数用于初始化静态数据成员。静态构造函数有如下特点:

  1、静态构造函数不能有访问修饰符和参数;

  2、静态构造函数不能访问实例成员;

  3、静态构造函数无法直接进行调用;

  结构和类的静态构造函数的触发规则不同,类的静态构造函数是在创建第一个实例或引用任何静态成员之前自动调用的,而结构的静态构造函数在以下情况调用:

  1、使用显式声明的构造函数进行初始化

  2、调用结构的方法或访问结构的静态数据成员(无论是读取还是赋值,访问实例数据成员不会触发CLR自动调用静态的构造函数)。

五、结构的多态和可继承性

  结构直接派生自System.ValueType,间接派生自System.Object,但结构是隐式密封的,不能作为基类在派生出其他的结构,也不能从类派生,但可以从接口派生。

  结构的特性:

  1、结构类型总是隐式密封的,因此在定义结构时不能使用sealed和abstract关键字;

  2、因为结构不能作为基类,结构的成员不能使用如下访问修饰符:protected和protected,internal;

  3、结构的函数成员不能声明为abstract和virtual,但是可以使用override关键字,用以覆写它的基类System.ValueType中的方法。

六、结构的装箱与拆箱

  结构是值类型,因此当它被转换为object类型时,或者它所实现的接口类型的时候,就会执行装箱操作;同样,当执行相反操作的时候,就会执行拆箱操作。

七、结构和类的对比

                       结构                    类
  数据类型                值类型                  引用类型
  是否必须使用new运算符实例化      否                    是
  是否可声明无参数的构造函数       否                    是
  数据成员可否在声明的同时初始化     声明为const或static可以,数据成员不可以  可以
  直接派生自什么类型           System.ValueType             有
  是否有析构函数             无                    有
  可否从类派生              否                    可以
  可否实现接口              可以                   可以
  实例化时在栈还是在堆分配内存      栈                    堆,栈中保存引用
  该类型的变量可否被赋值为null       否                    可以
  可否定义私有的无参构造函数       否                    可以
  是否总有一个默认的无参构造函数       是                    否

  无论结构使用预定义的、无参数的构造函数,还是使用用户定义的、有参数的构造函数进行初始化,都会初始化结构的数据成员。不过预定义的,无参的会将数值型初始化为默认值,引用类型初始化为null;而用户自定义的初始化策略对个成员进行初始化。因此结构类型的数据成员不允许在声明是显式初始化。

八、性能

  因为结构是值类型,因此在为结构分配内存,或者当结构超出了作用域被删除时,性能会非常好,因为他们将内联或者保存在堆栈中。当把一个结构类型的变量赋值给另一个结构时,对性能的影响取决于结构的大小,如果结构的数据成员非常多而且复杂,就会造成损失,接下来使用一段代码来说明这个问题。

  结构和类的适用场合分析:

  1、当堆栈的空间很有限,且有大量的逻辑对象时,创建类要比创建结构好一些;

  2、对于点、矩形和颜色这样的轻量对象,假如要声明一个含有许多个颜色对象的数组,则CLR需要为每个对象分配内存,在这种情况下,使用结构的成本较低;

  3、在表现抽象和多级别的对象层次时,类是最好的选择,因为结构不支持继承。

  4、大多数情况下,目标类型只是含有一些数据,或者以数据为主。

C# 结构体 struct的更多相关文章

  1. C语言结构体-struct

    知识点: 1)结构体的定义. 2)结构体的sizeof. 3)  结构体的指针. 1) 结构体的定义: 在逻辑上有一定关联的多个数据类型做为一整体进行操作的数据结构,它的关键字是struct.下面我将 ...

  2. 内核中用于数据接收的结构体struct msghdr(转)

    内核中用于数据接收的结构体struct msghdr(转) 我们从一个实际的数据包发送的例子入手,来看看其发送的具体流程,以及过程中涉及到的相关数据结构.在我们的虚拟机上发送icmp回显请求包,pin ...

  3. Swift中元组(Tuples),结构体(Struct),枚举(Enums)之间的区别

    Swift有许多种存储数据方式,你可以用枚举(enums),元组(tuples),结构体(structs),类(classes),在这篇文章中我们将比较枚举.元组.结构体之间区别,首先从最简单的开始- ...

  4. C语言 - 结构体(struct)比特字段(:) 详细解释

    结构体(struct)比特字段(:) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26722511 结构体(struc ...

  5. Go语言学习笔记(四)结构体struct & 接口Interface & 反射

    加 Golang学习 QQ群共同学习进步成家立业工作 ^-^ 群号:96933959 结构体struct struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套: go中的struc ...

  6. 结构体(struct)大小

    结构体(struct)大小 本文参考链接:C语言结构体(struct)常见使用方法,链接中的实例代码经实践有几处不准确,本文在引用时已做更改 注意:在结构体定义时不能申请空间(除非是结构体变量),不可 ...

  7. 结构体struct sockaddr_in, struct sockaddr,struct in_addr

    一.结构体 struct sockaddr_in,  struct sockaddr,  struct in_addr struct sockaddr_in,  struct sockaddr,str ...

  8. GO开发[五]:golang结构体struct

    Go结构体struct Go语言的结构体(struct)和其他语言的类(class)有同等的地位,但Go语言放弃了包括继承在内的大量面向对象特性,只保留了组合(composition)这个最基础的特性 ...

  9. 结构体struct、联合体union、枚举类型enum

    1.c语言中的类型 1)内置类型——char,short,int,float,double: 2)用户自定义类型(UDT)——struct结构体,union联合体,enum枚举类型 2.内存对齐 2. ...

  10. C++/C#:类Class与结构体Struct的区别

    C++中: 默认的访问控制.继承访问权限不同:struct时public的,class时 private的: 其它基本一样. C#中: struct是值类型,class是引用类型的: struct S ...

随机推荐

  1. mysql++ Query

    mysqlpp:: Query类存储了Connection的指针,可以用它进行SQL语句的增删改查. 连上数据库后,使用mysqlpp::Connection::query()获取Query对象 Qu ...

  2. vue监听浏览器窗口的变化,随着窗口变化调整里面table的宽高

    1.在data中设置: tableHeight:"500", screenHeight:window.innerHeight, 2.在mounted中设置: mounted() { ...

  3. HTML <meta> 标签 和 http-equiv

    前言 经常在写HTML,但是对于meta 的设置却一直疏于关注. <meta> 是什么 <meta> 是一个HTML的标签(辅助性标签). 它的位置位于文档的头部  <h ...

  4. Python(八)之函数

    Python函数 函数作用: (1)代码重用 (2)一种设计工具,分解复杂问题 (3)将相关功能打包并参数化 函数种类: 全局函数:定义在模块中 局部函数:嵌套在其他函数中 lambda函数:表达式 ...

  5. java多线程20 : ReentrantLock中的方法 ,公平锁和非公平锁

    公平锁与非公平锁 ReentrantLock有一个很大的特点,就是可以指定锁是公平锁还是非公平锁,公平锁表示线程获取锁的顺序是按照线程排队的顺序来分配的,而非公平锁就是一种获取锁的抢占机制,是随机获得 ...

  6. Win7窗口最大化和最小化快捷键

    原文: https://blog.csdn.net/u012269267/article/details/52484399 Windows 键 + 方向键“↑” 使当前使用的窗口最大化. Window ...

  7. java中判断字节数组的编码方式是不是UTF-8

    1,用google的工具包,配置maven: <!-- https://mvnrepository.com/artifact/com.googlecode.juniversalchardet/j ...

  8. WPF学习笔记(2)——动画效果按钮变长

    说明(2017-6-12 11:26:48): 1. 视频教程里是把一个按钮点击一下,慢慢变长: 注意几个方面: (1)RoutedEvent="Button.Click",这里面 ...

  9. XXE漏洞初窥

    前言: XXE Injection即XML External Entity Injection也就是XML外部实体注入攻击.漏洞是在对非安全的外部实体数据进⾏行处理时引发的安全问题. XML相关名词科 ...

  10. mysql行转列转换

    http://blog.csdn.net/sinat_27406925/article/details/77507478 mysql 行列转换 ,在项目中应用的极其频繁,尤其是一些金融项目里的报表.其 ...