C#高级编程笔记 Day 8, 2016年9月 28日 (数组)
1、数组的初始化
声明了数组后,就必须为数组分配内存,以保存数组的所有元素。数组是引用类型,所以必须给它分配堆上的内存,为此,应使用 new 运算符,指定数组中元素的类型和数量来初始化数组的变量。若使用了为未分配的元素,就会抛出NullReferenceExceptonl 类型的异常。
int myArray=new int[];

--> 在指定了数组的大小后,如果不复制数组中的所有元素,就不能重新设置数组的大小,如果事先不知道数组中应包含多少个元素,就可以使用集合。
下面使用数组初始化器为数组的每个元素赋值。数组初始化智能在声明数组变量时使用,不能在声明数组之后使用。
int[] myArray=new int[]{,,,}; //或者 int[] myArray=new int[]{,,,};.
2、数组支持协变,表示数组可以声明为基类,其派生类型的元素可以赋予数组元素。
static Person[] GetPerson()
{
return new Person[]{
new Person{FirstName="Damon",LastName="Hill"},
new Person{FirstName="Niki",LastName="Lauda"},
new Person{FirstName="Ayrton",LastName="Senna"}
};
}
数组协变只能用于引用类型,不能用于值类型。数组协变有一个问题,它只能通过运行时异常来解决。
如果把Person 数组赋予 object 数组,object数组就可以使用派生自object的任何元素。
例如,编译器允许把字符串传递给数组元素。但因为object 数组引用Person 数组,
所以就会出现以个运行时异常 ArrayTypeMismatchException.
3、ArraySegment<T>
结构ArraySegment<T>表示数组的一段,如果需要使用不同的方法处理某个大型方法的不同部分,那么可以把相应的数组部分复制到各个方法中。此时,与创建多个数组相比,更有效的方法是使用一本数组。将整个数组传递给不同的方法。这些方法中只是用数组的某个部分。方法的参数除了数组以外,还应包括数组内的偏移量以及该方法应该使用的元素数。这样一来,方法就需要至少三个参数。当使用数组段时,只需要一个参数就可以了。ArraySegment<T>结构包含了关于数组段的信息(偏移量和元素个数)。
SumOfSegments()方法提取一组ArraySegment<int>元素,计算改数组段定义的所有整数之和,并返回整数和
-
static int SumOfSegments(ArraySegment<int>[] segments)
{
int sum=;
foreach(var segment in segments)
{
for(int i=segment.Offset;i<segment.Offset+segment.Count;i++)
{
sum+=segment.Array[i];
}
}
return sum;
}
4、枚举:在foreach语句中使用枚举,可以迭代集合中的元素,且无须知道集合中的元素个数。foreach语句使用了一个枚举器。下图显示了调用 foreach 的客户端和集合之间的关系。数组或集合实现带GetEumerator()方法的IEumerable接口。GetEumerator()方法返回一个实现IEumerable接口的枚举。接着,foreach语句就可以使用IEumerable接口迭代集合了。

GetEnumerator()方法用IEnumerable接口定义。foreach语句并不真的需要在集合类中实现这个接口。有一个名为GetEnumerator()的方法,它返回实现了IEnumerator接口的对象就足够了
【扩展】
.NET Framework 的核心时其运行库执行环境 即Common Language
Runtime,称为公共语言运行库(CLR)或.NET 运行库。通常将在CLR控制下
运行的代码称为托管代码(managed code)。
但是,在CLR执行编写好的源代码(使用C#或其他语言编写的代码)之
前,需要编译它们。在.NET中,编译分为两个阶段:
(1)将源代码编译为Microsoft 中间语言(IL)。
(2)CLR把 IL编译为平台专用代码。
这两个阶段的编译过程非常重要,因为Microsoft中间语言时提供.NET 的许多优点的关键。
Microsoft中间语言与Java 字节码共享一种理念:他们都是低级语言,语法
很简单(使用数字代码,而不是文本代码),可以非常快速地转换为本地机器码。
对于代码,这种精心设计地通用语法有很重要地优点:平台无关性、提高性能、
和语言地互操作性。
5、IEnumerator接口
foreach语句使用IEnumerator接口的方法和属性,迭代集合中的所有元素。为此,IEnumerator定义了Current属性,来返回光标所在的元素,该接口的MoveNext()方法移动到集合的下一个元素上,如果有这个元素,该方法就返回true。如果集合不再有更多的元素,该方法就返回false。
foreach语句
C#的foreach语句不会解析为IL代码中的foreach语句。C#编译器会把foreach语句转换为IEnumerable接口的方法和属性。下面是一条简单的foreach语句,它迭代persons数组中的所有元素,并逐个显示它们:
foreach(var p in persons)
{
Console.WriteLine(p);
}foreach 语句会解析为下面的代码段。首先,调用GetEnumerator()方法,获得数组的一个枚举器。在while循环中——只要MoveNext()返回true——就用Current属性来访问数组中的元素:
IEnumerator<Person> enumerator=person.GetEnumerator();
while(enumerator.MoveNext())
{
Person p=enumeratoe.Current;
Console.WriteLine(p);
}
6、yield语句:以便创建枚举器。
yield ruturn 语句返回集合的一个元素,并移动到下一个元素。
yield break 可停止迭代
下面为一个使用yield return 语句实现一个简单集合的代码:HelloCollecetion 类包含GetEnumeration()方法。该方法实现代码包含两条 yield return 语句,它们分别返回字符串 Hello 和 World
using System;
using System.Collections; namspace com.test.yinxi
{
public class HelloCollection
{
public IEnumerator<string>GetEnumerator()
{
yield return "Hello";
yield return "World";
}
}
}包含yield 语句的方法或属性也称为迭代块。迭代块必须声明为返回
IEnumeration 或 IEnumerable 接口,或者这些接口的泛型版本,这个块
可以包含多条 yield return 语句 或 yield break 语句,但不能包含 return 语
句。
7、元组
数组合并了相同类型的对象,而元组合并了不同类型的对象。.NET Framework 定义了8个泛型Tuple 类和一个静态Tuple类,它们用作元组的工厂,不同泛型Tuple 类支持不同数量的元素。方法Divid()返回包含两个成员的元组 Tuple<int,int>。泛型类的参数定义了成员的类型,它们都是整数。元组用静态 Tuple 类的静态 Create() 方法创建。Create() 方法的泛型参数定义了要实例化的元组类型,新建的元组用 result 和 raminder 变量初始化,返回这两个变量相除的结果。
public static Tuple<int ,int> Divide(int dividend,int divisor)
{
int result =dividend/divisor;
int reminder=dividend%divisor; return Tuple.Create<int,int>(result,reminder);
} //调用
var result=Divide(,);
Console.WriteLine("result of division : {0},reminder: {1}",result.Item1,result.Item2);
如果元组包含的项超过8个,就可以使用带8个参数的Tuple类定义。最后一个模板参数是TRest,表示必须给它传递一个元组。这样,就可以创建带任意参数的元组了。
public class Tuple<T1,T2,T3,T4,T5,T6,T7,TRest>
其中,最后一个模板参数是一个元组类型,所以可以创建带任意多项的元组:
var tuple =Tuple.Create<string,string,string ,int ,int ,int ,double, Tuple<int,int>>("Stenphanie","Alina","Nagel",,,,1.37,Tuple.Create<int,int>(,));
8、【专题】结构比较
数组和元组都实现接口IStructuralEquatable和IStructuralComparable。这两个接口都是.NET 4 新增的,不仅可以比较引用,还可以比较内容。这些接口都是现实实现的,所以在使用时需要把数组和元组强制转换为这个接口。IStructuralEquatable接口用于比较两个元组或数组是否有相同的内容,IStructuralComparable接口用于给数组或元组排序。下面为一个实现 IEquatable 接口的Person类。IEquatable接口定义了一个强类型化的Equals()方法,以比较FirstName 和LastName属性的值。
public class Person :IEquatable<Person>
{
public int Id{get;private set;}
public string FirstName{get;set;}
public string LastName{get;set;} public override string ToString()
{
return String.Format("{0},{1},{2}",Id,FirstName,LastName);
} public override bool Equals(object obj)
{
if(obj==null)
{
return base.Equals(obj);
}
return Equals(obj as Person);
} public override int GetHashCode()
{
return Id.GetHashCode();
} public bool Equals(Person other)
{
if(other==null)
{
return base.Equals(other);
}
return this.Id==other.Id && this.FirstName==oher.FirstName&&this.LastName==other.LastName;
}
}接下来创建了两个包含Person项的数组。这两个数组通过变量名janet 包含相同的Person对象,和两个内容相同的不同Person对象。比较运算符“!=”返回 true,因为这其实是两个变量person1 和 persons2医用的两个不同数组。因为 Array类没有重写带一个参数的Equals方法,所以用“==”运算符比较引用也会得到相同的结果,即这两个变量不相同。
var janet =new Person{FirstName="Janet",LastName="Jackson"};
Person[] persons1={
new Person
{
FirstName="Michael",
LastName="Jackson"
}.
janet
};
Person[] persons2={
new Person
{
FirstName="Michael",
LastName="Jackson"
},
janet
};
if(persons1!=persons2)
{
Console.WrilteLine("not the same reference!");
}
C#高级编程笔记 Day 8, 2016年9月 28日 (数组)的更多相关文章
- 2016年12月28日 星期三 --出埃及记 Exodus 21:23
2016年12月28日 星期三 --出埃及记 Exodus 21:23 But if there is serious injury, you are to take life for life,若有 ...
- 2016年11月28日 星期一 --出埃及记 Exodus 20:19
2016年11月28日 星期一 --出埃及记 Exodus 20:19 and said to Moses, "Speak to us yourself and we will listen ...
- 2016年10月28日 星期五 --出埃及记 Exodus 19:13
2016年10月28日 星期五 --出埃及记 Exodus 19:13 He shall surely be stoned or shot with arrows; not a hand is to ...
- 2016年6月28日 星期二 --出埃及记 Exodus 14:25
2016年6月28日 星期二 --出埃及记 Exodus 14:25 He made the wheels of their chariots come off so that they had di ...
- 大陆地区OpenStack项目Core现状(截至2016年1月28日,转载自陈沙克日志)
陈沙克 经常有朋友问,大陆地区大概有多少位OpenStack项目的Core.这个问题,现在其实不太好回答,如果需要准确统计的话.下面仅仅是一个大概估计,有遗漏的,希望朋友指出,我来补全. 文档修改历史 ...
- 高薪诚聘熟悉ABP框架的.NET高级开发工程师(2016年7月28日重发)
招聘单位是ABP架构设计交流群(134710707)群主阳铭所在的公司-上海运图贸易有限公司 招聘岗位:.NET高级开发工程师工作地点:上海-普陀区 [公司情况]上海运图贸易有限公司,是由易迅网的创始 ...
- 2016年11月28日--ADO.Net 查、插、删、改 小练习
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 2016年11月28日--ADO.Net 增、删、改、查
数据访问 对应命名空间:System.Data.SqlClient; SqlConnection:连接对象SqlCommand:命令对象SqlDataReader:读取器对象 CommandText: ...
- 【第400篇题解纪念2016年10月28日】【28.10%】【codeforces 617E】XOR and Favorite Number
time limit per test4 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
随机推荐
- python_爬虫一之爬取糗事百科上的段子
目标 抓取糗事百科上的段子 实现每按一次回车显示一个段子 输入想要看的页数,按 'Q' 或者 'q' 退出 实现思路 目标网址:糗事百科 使用requests抓取页面 requests官方教程 使用 ...
- Android开发之InstanceState详解
Android开发之InstanceState详解 本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...
- xcode6 beta 中智能提示(自动完成)功能有时不显示的问题
xcode6 beta 中智能提示(自动完成)功能有时不显示的问题 周银辉 xcode6 beta 中智能提示(自动完成)功能有时不显示,这让人很郁闷啊,网上老外的视频中看人家用的好好的. ...
- 学习SAP HANA SQL
学习SAP HANA SQL 语句(创建 EMP,DEPT,BONUS 和 SALGRADE测试表)--像学Oracle一样学习SAP HANA 标签: sap测试oraclesqltableda ...
- Dell xps 13 9350待机时总是关机的处理方法
现象: 年初买的dell xps13 9350,最近可能是由于win10做了一些更新,每次睡眠就自动关机了,重启很多次,修改电源选项都没用, 原因分析: 在网上搜了一下,有人发现xps15 9350也 ...
- ios9适配系列教程——ios9新变化
Demo1_iOS9网络适配_改用更安全的HTTPS iOS9把所有的http请求都改为https了:iOS9系统发送的网络请求将统一使用TLS 1.2 SSL.采用TLS 1.2 协议,目的是 强制 ...
- DbUtility v3
DbUtility v3 历史 七年前,也就是2007年,我在博客园写了一篇博文,开源并发布了恐怕是我第一个开源项目,DbUtility.其设计的初衷就是为了简化ADO.NET繁琐的数据库访问过程,提 ...
- checking for fcc ....no checking for cc .. no
源码编译,提示缺少gcc cc cl.exe 解决方案: yum install -y gcc glibc
- Android四大组件之—— 使用服务进行后台操作
什么是服务 服务是一个没有可视化界面的组件,它可以在后台长期运行并进行各种操作. 服务的创建 我们只需要继承Service类并实现相应的方法即可创建服务 要想启动服务,还得在AndroidManife ...
- django static文件的引入方式
1. 在django project中创建 static文件夹 2.settings.py中配置要在 STATIC_URL = '/static/' 下边 STATICFILES_DIRS = [ ...