一步一步学c#(六):数组
数组
简单数组
如果需要使用同一个类型的多个对象,就可以使用数组。数组是一种数据结构,它可以包含同一类型的多个元素。
数组声明:int[] myArray
使用new运算符,指定数组中元素的类型和数量来初始化数组的变量。指定数组的大小:
myArray=new int[4]
声明和初始化数组后,变量myArray就引用了4个整形值,它们位于托管堆上:

在一个语句中声明和初始化数组
int[] myArray=new int[4];
使用数组初始化器为数组的每个元素赋值。
int[] myArray=new int[4]{4,7,11,2};
访问数组元素
数组只支持有整型参数的索引器。索引器总是以0开始,表示第一个元素,可以传递给索引器的最大值是元素个数减1,因为索引从0开始。数组myArray用4个整型值声明和初始化。用索引器对应的值0,1,2,3就可以访问数组中的元素。

在for语句中使用Length属性,在不知道数组中的元素个数的情况下:
使用引用类型
除了能声明预定义类型的数组,还可以声明自定义类型的数组。用Person类来说明,这个类有自动实现的属性Firstname和Lastname.以及Object类重写的ToString()方法;

使用从0开始的索引器,可以为数组的每个元素分配内存:

下图显示了Person数组中的对象在托管堆中的情况。mypersons是储存在栈上的一个变量,该变量引用了储存在托管堆上的Pweson元素对应的数组。


多维数组
一般数组(也称为一维数组)用一个整数来索引,多维数组用两个或多个整数来索引。
二维数组的科学表示法:


声明数组之后,就不能修改其阶数了。
如果事先知道元素的值,则也可以使用数组索引器来初始化二维数组。

使用数组初始化时,必须初始化数组的每个元素,不能遗漏任何元素。

锯齿数组
二维数组

锯齿数组

在声明锯齿数组时,要依次放置左右括号。只在第一对括号中放置该数组包含的行数,定义各行中元素个数的第二个括号设置为空,因为这类数组的每一行包含不同的元素个数,之后,为每一个指定行中的元素个数:

迭代锯齿数组中所有元素的代码可以放在嵌套的for循环中。在外层的for循环中迭代每一行,在内层的for循环中迭代一行中的每个元素:


Array类
创建数组
Array类是一个抽象类,所以不能使用构造函数来创建数组。但除了可以使用c#语法创建数组实例之外,还可以使用静态方法CreateInstance()创建数组。
例子说明了如何创建类型int,大小为5的数组。






复制数组
因为数组是引用类型,所以将一个数组变量赋予另一个数组变量,就会得到两个引用同一数组的变量。而复制数组,会使数组实现IConeable。

如果数组包含引用类型,则不复制元素,而只复制引用。


显示变量beatles和beatlesClone,其中beatlesClone通过从beatles中调用Clone()方法创建。
Clone()方法和Copy()方法的区别:Clone()方法会创建一个新数组,而Copy()方法必须传递阶数相同且有足够元素的已有数组。
排序
Array类使用QuickSory算法对数组中元素的进行排序。
示例程序中,数组name包含string类型的元素,这个数组可以排序》

}

如果对数组使用自定义类。就必须实现IComparabe接口。此接口只定义了一个方法CompareTo(),如果要比较的对象相等,该方法就返回0.如果该实例应排在参数对象的前面,该方法就返回小于0的值,相反,就大于0的值。

LastName的值相同,就比较FirstName。
就可以按姓氏对Person对象对应的数组排列:


假如Person对象排序不同,就可以实现IComparer接口或IComparer<T>接口,定义Compare().IComparer接口独立于比较的类。

类PersonComparer实现了IComparer<Person>接口,按照firstName或lastName对Person对象排序。实现Compare()方法时用了一个switch语句指定是按FirstName还是LastName排序。
按名字对person数组排序:


数组作为参数
数组可以作为参数传递给方法。要返回数组,要将数组声明为返回类型。
GetPerson()所示:


数组协变
数组可以声明为基类,派生元素可以赋予数组元素。
声明object[]类型的参数,给它传递一个Perxon[]:

数组协变只能用于引用类型,不能用于值类型。
ArraySegment<T>表示数组的一段。如果某个方法只返回数组的一部份或给某方法传递数组的一部分,就可以用。
SumOfSegments<T>方法提取一组,ArraySegment<int>元素,计算数组定义的所有整数之和,并返回整数和:

使用这个方法时,传递一个数组段。第一个数组元素从ar1的第一个元素开始,引用了3个元素,第二个数组从ar2的第四个元素开始,引用3个元素:


枚举
在foreach语句中用枚举,可以迭代集合的元素,且无需知道集合中的元素个数。
下图显示了调用foreach方法的客户端和集合之间的关系。

foreach语句
首先foreach语句不会解析IL代码中的foreach语句。编译器会将它转换为IEnumerable借口的方法和属性。
foreach (var p in person)
{
Console.WriteLine(p);
}
它迭代persons数组中的所有元素,并逐个显示。
foreach解析的代码段。

调用GetEnumerator()方法,获取数组枚举器。在While循环中——只要MoveNext()返回ture---就用Current属性访问数组中的元素。
yleld语句
用yiled retum语句实现一个简单集合的代码。

包含yield语句的方法或属性也称为迭代块。
用foreach语句迭代集合;

使用迭代块,编译器会生成一个yield类型,其中包含一个状态机。


yield类型实现IEnumerator和IDisposable接口的属性和方法。可以吧yield类型看做内部类Enumerator. yield语句会生成一个枚举器,而不仅仅生成一个包含的项的列表。
迭代集合的不同方式
在下面的这个比hello Word示例略大但比较真实的示例中,可以使用yield return语句,以不同方式迭代集合的类。

类MUSICTitles可以用默认方式通过GetEnumerator()方法迭代标题,用Reverse()方法逆序迭代标题,用stubset()方法迭代子集。
默认使用的方法,迭代字符串数组的客户端代码先使用GetEnumerator()方法。
用yield retum返回枚举器
从yield return中返回枚举器。

在Tic Tac Top游戏中有9个域,玩家轮流在这些域中放置一个十字或一个圆。
使用Game Moves类。 第一次调用enumerator.MoveNext()时。会调用Cross()方法。


元组
数组合并了相同类型的对象,而元组合并了不同的对象。
新建的元组用result和reminder变量初始化,返回这两个变量相除的结果:

下面代码说明了divide()方法的调用:

结构比较
IstructuralEquatable接口用于比较两个元素或数组是否有相同的内容,IstructuralComparable接口用于给元素或数组排序。
说明IstructuralEquatable接口的实例,使用实现IEquatable接口的Person类。


创建两个包含person项的数组。他们通过变量名Janet包含相同的person对象,和两个内容相同的不同person对象。

对于IstructuralEquatable接口定义的Equals()方法,第一个参数是object,第二个参数是IEqualityComparer类型。
person实现IEquatable<Person>,比较的对象的内容,数组确保含相同的内容:


如何执行相同的操作:

Tuple<>提供了两个Equlas()方法:一个重写了object基类中的Equals()方法,并把object作为参数,第二个由IStructuralEqualityComparer接口定义,并把object和IEqualityComparer作为参数。
给第一个方法传送另一个元组。

使用类TupleComparer创建一个自定义的IEqualityComparer.

一步一步学c#(六):数组的更多相关文章
- 一步一步学Vue(六)https://www.cnblogs.com/Johnzhang/p/7242640.html
一步一步学Vue(六):https://www.cnblogs.com/Johnzhang/p/7237065.html 路由 一步一步学Vue(七):https://www.cnblogs.com ...
- 一步一步学android控件(之十六)—— CheckBox
根据使用场景不同,有时候使用系统默认的CheckBox样式就可以了,但是有时候就需要自定义CheckBox的样式.今天主要学习如何自定义CheckBox样式.在CheckBox状态改变时有时需要做一些 ...
- 一步一步学Vue(六)
本篇继续介绍vue-router,我们需要要完成这样个demo:<分页显示文章列表>:这里我们以博客园首页列表为例简化处理: 按照上图框选所示,简单分为蓝色部分文章组件(ArticleIt ...
- 一步一步学ROP之linux_x64篇
一步一步学ROP之linux_x64篇 一.序 **ROP的全称为Return-oriented programming(返回导向编程),这是一种高级的内存攻击技术可以用来绕过现代操作系统的各种通用防 ...
- 一步一步学ROP之linux_x86篇
一步一步学ROP之linux_x86篇 作者:蒸米@阿里聚安全 一.序 ROP的全称为Return-oriented programming(返回导向编程),这是一种高级的内存攻击技术可以用来绕过 ...
- (转载)一步一步学Linq to sql系列文章
现在Linq to sql的资料还不是很多,本人水平有限,如果有错或者误导请指出,谢谢. 一步一步学Linq to sql(一):预备知识 一步一步学Linq to sql(二):DataContex ...
- 一步一步学ZedBoard & Zynq(四):基于AXI Lite 总线的从设备IP设计
本帖最后由 xinxincaijq 于 2013-1-9 10:27 编辑 一步一步学ZedBoard & Zynq(四):基于AXI Lite 总线的从设备IP设计 转自博客:http:// ...
- 一步一步学Python(2) 连接多台主机执行脚本
最近在客户现场,每日都需要巡检大量主机系统的备库信息.如果一台台执行,时间浪费的就太冤枉了. 参考同事之前写的一个python脚本,配合各主机上写好的shell检查脚本,实现一次操作得到所有巡检结果. ...
- 【DG】[三思笔记]一步一步学DataGuard
[DG][三思笔记]一步一步学DataGuard 它有无数个名字,有人叫它dg,有人叫它数据卫士,有人叫它data guard,在oracle的各项特性中它有着举足轻理的地位,它就是(掌声)..... ...
- 一步一步学Silverlight 2系列(6):键盘事件处理
一步一步学Silverlight 2系列(6):键盘事件处理 概述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言V ...
随机推荐
- 多字节字符与界面 manifest
之前把调试项目的时候软件界面变成了很古板的那种界面,后来查了一会发现因为字符集的改变,个人习惯统一我一般用同一种字符集,虽然Unicode只涉及语言问题,不过总感觉它占内存,用非字符集,搜索发现将代码 ...
- LINUX查看硬件配置命令
LINUX查看硬件配置命令 系统 # uname -a # 查看内核/操作系统/CPU信息 # head -n 1 /etc/issue # 查看操作系统版本 # cat /proc/cpuinf ...
- flex4 日期类型字符串转日期类型(string转Date)(转)
mysql数据库中存储的日期类型通过PHP返回到flex端为字符串类型,这样在flex中进行处理时就必须要将字符串转化为Date类型.如果仅仅是 "年/月/日" 的组合,而没有涉及 ...
- 计算机原理学习(2)-- 存储器和I/O设备和总线
前言 前一篇文章介绍了冯诺依曼体系结构的计算机的基本工作原理,其中主要介绍了CPU的结构和工作原理.这一篇主要来介绍存储区,总线,以及IO设备等其他几大组件,来了解整个计算机是如何工作的. 这些东西都 ...
- IE8 多进程问题
IE8的一个重要特性就是每个Tab(选项卡)在独立的进程中运行,我们称之为LCIE(Loosely-Coupled IE). 所以大家在升级到IE8之后会发现资源管理器里面有两个或者多个iexplor ...
- js 使用for循环遍历数组
今天写个无聊的东西!for循环的使用! 例如以下:定义a数组,b为伪数组! var a = [1,2,3,0,5,4]; var b = document.getElementsByTagName(' ...
- HDU 4914 Linear recursive sequence(矩阵乘法递推的优化)
题解见X姐的论文 矩阵乘法递推的优化.仅仅是mark一下. .
- (转)Web开发中最致命的小错误
Web开发中最致命的小错误 现在,有越来越多所谓的“教程”来帮助我们提高网站的易用性.本文收集了一些在 Web 开发中容易出错和被忽略的小问题,并且提供了参考的解决方案,以便于帮助 Web 开发者更好 ...
- VisualStudio中的代码段
VS很强大,在这里就不过多说了,在平时码代码时应用代码段会提高我们的编写速度. 举个例子: 比如输入Console.WriteLine (); 传统方法就是一个字母一个字母的输入进去. 如果大家掌握了 ...
- JavaScript引用类型之Array数组的concat()和push()方法的区别
在javascript中,我们一般都只用push向数组的尾部插入新元素的,但是其实在javascript中还有另外一个方法和push一样,也是向数组尾部插入新元素的,但是他们之间却存在着一定的区别,当 ...