结构是使用 struct 关键字定义的,与类相似,都表示可以包含数据成员和函数成员的数据结构。 一般情况下,我们很少使用结构,而且很多人也并不建议使用结构,但作为.NET Framework 一般型別系统中的一个基本架构,还是有必要了解一下的。

结构的特征: 结构是一种值类型,并且不需要堆分配。 结构的实例化可以不使用 new 运算符。

在结构声明中,除非字段被声明为 const 或 static,否则无法初始化。 结构类型永远不是抽象的,并且始终是隐式密封的,因此在结构声明中不允许使用abstract和sealed修饰符。

结构不能声明默认构造函数(没有参数的构造函数)或析构函数,但可以声明带参数的构造函数。 结构可以实现接口,但不能从另一个结构或类继承,而且不能作为一个类的基,所有结构都直接继承自System.ValueType,后者继承自 System.Object。 结构在赋值时进行复制。 将结构赋值给新变量时,将复制所有数据,并且对新副本所做的任何修改不会更改原始副本的数据。 在使用值类型的集合(如 Dictionary

struct A
{
public int x; //不能直接对其进行赋值
public int y;
public static string str = null; //静态变量可以初始化
public A(int x,int y) //带参数的构造函数
{
this.x = x;
this.y = y;
Console.WriteLine("x={0},y={1},str={2}", x, y,str);
}

}
class Program
{
static void Main(string[] args)
{
A a = new A(1,2);
A a1 = a;
a.x = 10;
Console.WriteLine("a1.x={0}",a1.x);
Console.Read();
}
}

结果为:x=1,y=2,str=            a1.x=1 此时a1.x值为1是因为,将a赋值给a1是对值进行复制,因此,a1不会受到a.x赋值得改变而改变。

但如果A是类,这时a和a1里的x引用的是同一个地址,则a1.x的值会输出10。

结构的装箱与拆箱

我们知道,一个类类型的值可以转换为 object 类型或由该类实现的接口类型,这只需在编译时把对应的引用当作另一个类型处理即可。 与此类似,一个object 类型的值或者接口类型的值也可以被转换回类类型而不必更改相应的引用。当然,在这种情况下,需要进行运行时类型检查。 由于结构不是引用类型,上述操作对结构类型是以不同的方式实现的。 当结构类型的值被转换为object 类型或由该结构实现的接口类型时,就会执行一次装箱操作。 反之,当 object 类型的值或接口类型的值被转换回结构类型时,会执行一次拆箱操作。 与对类类型进行的相同操作相比,主要区别在于: 装箱操作会把相关的结构值复制为已被装箱的实例,而拆箱则会从已被装箱的实例中复制出一个结构值。 因此,在装箱或拆箱操作后,对“箱”外的结构进行的更改不会影响已被装箱的结构。

struct Program
{
static void Main(string[] args)
{
int i = 1;
object o = i; //隐式装箱
i = 123;
Console.WriteLine("i={0},o={1}",i,o);
Console.Read();
}
}
//结果为:i=123,o=1

 结构与构造函数 

我们知道结构不能使用默认的构造函数,只能使用带参数的构造函数,当定义带参数的构造函数时,一定要完成结构所有字段的初始化,如果没有完成所有字段的初始化,编译时会发生错误­。 结构可以使用静态构造函数吗? 可以,结构的静态构造函数与类的静态构造函数所遵循的规则大体相同。 结构的静态构造函数何时将触发呢? 结构的实例成员被引用,结构的静态成员被引用,结构显示声明的构造函数被调用。 但是创建结构类型的默认值不会触发静态构造函数。为什么结构不能自定义无参数的构造函数? 结构类型的构造函数与类的构造函数类似,用来初始化结构的成员变量,但是struct不能包含显式默认构造函数, 因为编译器将自动提供一个构造函数,此构造函数将结构中的每个字段初始化为默认值表中显示的默认值。 然而,只有当结构用new实例化时,才会调用此默认构造函数。对值类型调用默认构造函数不是必需的。

struct A
{
static A()
{
Console.WriteLine("I am A.");
}
public void Fun()
{

}
}
class Program
{
static void Main(string[] args)
{
A a=new A();
a.Fun(); //结构的实例成员被引用
Console.Read();
}
}
结果为:I am A.

 结构与继承: 

一个结构声明可以指定实现的接口列表,但是不能指定基类。 由于结构不支持类与结构的继承,所以结构成员的声明可访问性不能是 protected 或 protected internal。 结构中的函数成员不能是 abstract 或 virtual,因而 override 修饰符只适用于重写从 System.ValueType 继承的方法。 为在设计编程语言时将结构设计成无继承性?­ 其实类的继承是有相当的成本的 ——由于继承性,每个类需要用额外的数据空间来存储“继承图”来表示类的传承历史, 通俗地说来就是我们人类的家族家谱,里面存储着我们的祖宗十八代,只有这样我们才知道我们从哪里来的,而家谱肯定是需要额外的空间来存放的。 大家不要觉得这个存放“继承图”的空间很小,如果我们的程序需要用10000个点(Point)来存放游戏中的人物形体数据的话, 在一个场景中又有N个人,这个内存开销可不是小数目了。所以我们可以通过将点(Point)申明成 Struct而不是class来节约内存空间。

interface ITest
{
void Fun(int x,int y);
}
struct A:ITest
{
public void Fun(int x,int y) //隐式实现接口里的方法
{
Console.WriteLine("x={0},y={1}", x, y);
}
}
class Program
{
static void Main(string[] args)
{
A a; //结构的实例化可以不使用new
a.Fun(1, 2);
Console.Read();
}
}
// 结果为:x=1,y=2

 什么情况下结构的实例化可以不使用new?

当结构中没有参数时,结构的实例化可以不使用new;

当结构中有参数时,必须对结构中所有参数进行初始化后,才能不使用new对结构进行实例化。

什么时候使用结构?

结构体适合一些小型数据结构,这些数据结构包含的数据以创建结构后不修改的数据为主;

例如:struct类型适于表示Point、Rectangle和Color等轻量对象。

尽管可以将一个点表示为类,但在某些情况下,使用结构更有效。

如果声明一个10000个Point对象组成的数组,为了引用每个对象,则需分配更多内存;这种情况下,使用结构可以节约资源。­

定义的时候不会用到面向对象的一些特性;

结构体在不发生装箱拆箱的情况下性能比类类型是高很多的.

struct结构体(剽窃别人的)的更多相关文章

  1. C# Struct结构体里数组长度的指定

    typedef struct Point{ unsigned short x; unsigned short y; }mPoint;//点坐标 typedef struct Line{ mPoint ...

  2. C#基础--struct(结构体)

    结构体和类有点类似    我们定义一个类的时候    是class   类名   定义结构体的时候是 struct   结构体名 结构体的写法 struct Point { // public int ...

  3. 1.0 基础、标示符、常量、数据类型(enum 枚举,struct 结构体)、操作符、循环、数组

    一.程序 现实生活中,程序是指完成某些事务的一种既定方法和过程,可以把程序看成是一系列动作执行过程的描述. 在计算机世界,程序是指令,即为了让计算机执行某些操作或解决某个问题而编写的一系列有序指令的集 ...

  4. C#语言struct结构体适用场景和注意事项

    在C#语言中struct结构体和class之间的区别主要是值类型和引用类型的区别,但实际上如果使用不当是非常要命的.从Win32时代过来的人对于struct一点不感觉陌生,但是却反而忽略了一些基本问题 ...

  5. C语言 Struct 结构体在 Java 中的体现

    大一整个学期完成了 C 语言的学习,大二就进入了Java 的学习. 和C语言一样,我们都会尝试写一个小小的学生管理系统什么的,学习过 C 语言同学知道,在管理系统中 Struct 结构体是个很好用的东 ...

  6. Swift Struct 结构体

    前言 Swift 语言有两种基本的数据类型,即类(class)和结构体(struct),class 这样的概念大家不会陌生,而 struct 也并不是什么新的概念,在 Objective-C 和 C ...

  7. go struct结构体

    struct结构体 用来自定义复杂数据结构 struct里面可以包含多个字段(属性),字段可以是任意类型 struct类型可以定义方法,注意和函数的区分 struct类型是值类型 struct类型可以 ...

  8. struct 结构体解析(原)

    (一)基本概念 结构体是一个或是多个变量的集合,这些变量可能为不同的类型,为了处理的方便而将这些变量组合在一个名字之下.我们将关键字struct引入了结构声明中.结构声明包含在花括号内的一系列声明组成 ...

  9. struct结构体在c和c++中的差别

    非常多次遇到这个struct的问题,今天在这里简单总结一下我的理解 一.struct在C 中的使用 1.单独使用struct定义结构体类型 struct Student { int id; int n ...

  10. Go - Struct 结构体

    目录 概述 声明结构体 生成 JSON 改变数据 推荐阅读 概述 结构体是将零个或多个任意类型的变量,组合在一起的聚合数据类型,也可以看做是数据的集合. 声明结构体 //demo_11.go pack ...

随机推荐

  1. Javascript模块化编程(三):require.js的用法(转)

    这个系列的第一部分和第二部分,介绍了Javascript模块原型和理论概念,今天介绍如何将它们用于实战. 我采用的是一个非常流行的库require.js. 一.为什么要用require.js? 最早的 ...

  2. 用于svn添加当前目录下所有未追踪的文件,和删除所有手动删除的文件的脚本

    由于要经常用到类似与 git 中的 git add --all 这种操作,但是发现svn中并不支持类似的操作. 虽然可以使用 wildcard 进行匹配,但是 wildcard是在shell中进行匹配 ...

  3. Your intuition 你的直觉

    If you’re thinking just like everyone else, you aren’t really thinking. Follow your intuition. Do wh ...

  4. EF并非我们想象的那么智能

    我之前在项目中用EF读取一个视图的数据,页面展示出现重复数据,当时百思不得其解,跟踪代码,数据读取时取到的数据并不是重复,为什么在前台显示就有重复了呢,我当时就在业务层将数据去重,但取到的数据跟数据库 ...

  5. 关于MySQL相关的查看显示信息:

    关于MySQL相关的查看显示信息: 数据库范围: 一.查看所有的数据库:(仅仅是看数据库数量与名字) mysql> show databases; 二.查看某个数据库的创建信息:(主要看数据库的 ...

  6. 原生态PHP+mysql 实现分页

    <?php/** * 数据分页 * 时间:2016-07-06 *//**1传入页码**/ $page = $_GET['p'];/**2根据页码取数据:php->mysql处理**/$h ...

  7. iOS8.3发布了Swift 1.2带来哪些新变化

    苹果前几日在面向开发者推送iOS 8.3 Beta的同时,还发布了版本号为6D520o的Xcode 6.3 Beta,其中便包含了iOS 8.3 Beta和OS X v10.10 SDK,并进一步提升 ...

  8. TortoiseGit使用手册

    1 安装 1.1 32位系统 1.2 64位系统 2 配置 2.1 设置语言 2.2 配置用户信息 2.3 生成ssh-key(仅限第一次使用) 2.4 初始化仓库(尚未使用git管理的项目) 2.5 ...

  9. 读书笔记:《HTML5开发手册》

    一.HTML5中新的结构元素 1. HTML5初始文件 1.1.doctype 在之前,doctype的声明是这样的: <!DOCTYPE HTML PUBLIC "-//W3C//D ...

  10. Android study --- 广播

    广播接收者 在Android系统运行时会产生很多事件,事件产生时,回想系统发送广播,只要向系统发送广播,系统就知道发生了相应的事件,从而执行相对应的代码.在系统中只要使用广播接受者,就可以接收广播 创 ...