C#入门经典(第五版)学习笔记(四)
---------------集合、比较和转换---------------
C#中的数组是作为System.Array类的实例实现的,它们是集合类(Collection Classes)中的一种类型。
集合类一般用于处理对象列表,大多通过实现System.Collections名称空间中的接口而获得的
System.Collections名称空间中的几个接口提供了基本的集合功能:
1)IEnumerable可以迭代集合中的项。
2)ICollection(继承于IEnumerable)可以获取集合中的项的个数,并能把项复制到一个简单的数组类型中。
3)IList(继承于IEnumerable和ICollection)提供了集合的项列表,允许访问这些项,并提供其他一些与项列表相关的基本功能
4)IDictionary(继承于IEnumerable和ICollection)类似于IList,但提供了可通过键值(而不是索引)访问的项列表。
System.Array类实现了IList、ICollection和IEnumerable,但不支持IList的一些更高级的功能,它表示大小固定的项列表。
数组初始化需要固定大小,ArrayList集合则不用
Animal[] animalArray = new Animal[2];
ArrayList animalArrayList = new ArrayList();
这个类还有两个构造函数:
1、把现有集合作为参数复制到新实例中
2、用一个int参数设置集合的容量,不过实际内容超过容量时会自动增加
初始化数组,需要给这个项目赋予初始化了的对象 例如:
Cow myCow1 = new Cow("Deirdre");
animalArray[] = myCow1;
animalArray[] = new Chicken("Ken");
可以用这两种方式初始化数组
对于ArrayList集合,需要用Add()方法添加新项目
例如:
Cow myCow2 = new Cow("Hayley");
animalArrayList.Add(myCow2);
animalArrayList.Add(new Chicken("Roy"));
在添加完项目之后,就可以用与数组相同的语法重写他们
例如:
animalArrayList[] = new Chicken("Roy2")
Array数组和ArrayList集合都支持foreach结构来迭代
例如:
foreach (Animal myAnimal in animalArray)
{
}
foreach (Animal myAnimal in animalArrayList)
{
}
Array数组使用Length属性获取项目的个数
例如:
int animalCount = animalArray.Length;
ArrayList集合使用Count属性获取项目的个数
int animalCount2 = animalArrayList.Count;
Array数组是强类型化的,可以直接使用数组的类型来存储项目
即可以直接访问项目的属性和方法
例如:
对于类型是Animal的数组,Feed()是类Animal的方法
animalArray[].Feed();
但对于类Animal派生类的方法,就不能直接调用,需要强制转换
((Chicken)animalArray[]).LayEgg();
使用Remove()和RemoveAt()方法删除项目
Remove 从 ArrayList 中移除特定对象的第一个匹配项(参数为特定对象)
RemoveAt 移除 ArrayList 的指定索引处的元素(参数为索引值) 删除项目后,会使其他项目在数组中移动一个位置
使用AddRange()和InsertRange()方法可以一次添加多个项目
AddRange 将 ICollection 的元素添加到 ArrayList 的末尾
InsertRange 将集合中的某个元素插入 ArrayList 的指定索引处。 例如:
animalArrayList.AddRange(animalArray);
使用IndexOf()方法获取指定项目的索引值
IndexOf 返回 ArrayList 或它的一部分中某个值的第一个匹配项的从零开始的索引。
可以通过索引值直接访问选项
例如:
int iIndex = animalArrayList.IndexOf(myCow1);
((Animal)animalArrayList[iIndex]).Feed();
定义集合
从System.Collections.CollectionBase这个抽象类中派生自己的集合,此类提供了集合类的许多实现方法
CollectionBase类有IEumerable、ICollection和IList接口
CollectionBase提供了两个受保护的属性,可访问存储的对象本身,分别为List和InnerList,List可以通过IList接口访问项,InnerList是用于存储项的ArrayList对象
集合类定义举例:
public class Animals:CollectionBase
{
public void Add(Animal newAnimal)
{
List.Add(newAnimal);
}
public void Remove(Animal oldAnimal)
{
List.Remove(oldAnimal);
}
public Animals(){}
}
使用ArrayList实现代码处理对象
Animals animalCollection = new Animals();
animalCollection.Add(new Cow("Cow1"));
foreach(Animal myAnimal in animalCollection)
{
Console.WriteLine("{0} {1}",myAnimal.ToString(),myAnimal.Name);
}
不能用animalCollection[0].Feed();因为没有索引符
索引符可添加到类中,使之提供类似于数组的访问,例如:
public class Animals:CollectionBase
{
public Animal this[int animalIndex]
{
get{return (Animal)List[animalIndex];}
set{List[animalIndex] = value;}
}
}
如此即可使用上面无法使用的animalCollection[0].Feed();
关键字值集合和IDictionary
与索引的集合一样,可使用一个基类简化IDictionary接口的实现,即DictionaryBase,它也实现IEnumerable和ICollection
关键字值集合举例:
public class Animals:DictionaryBase
{
public void Add(string newID,Animal newAnimal)
{
Dictionary.Add(newID,newAnimal);
}
public void Remove(string animalID)
{
Dictionary.Remove(animalID);
}
public Animals(){}
public Animal this[string animalID]
{
get{return (Animal)Dictionary[animalID];}
set{Dictionary[animalID] = value;}
}
}
字典集合有个继承于DictionaryBase的成员Dictionary,此成员是一个IDictionary接口
使用foreach和DictionaryBase派生类可以提供DictionaryEntry结构,例如:
foreach(DictionaryEntry myEntry in animalCollection)
{
Console.WriteLine("{0} {1}",myEntry.Value.ToString(),((Animal)myEntry.Value).Name);
}
如果要直接通过foreach提取Animal对象,最简单的方式是实现一个迭代器
迭代器
IEnumerable接口负责使用foreach循环,在foreach循环中,迭代集合collectionObject的过程如下:
1)调用collectionObject.GetEnumerator(),返回一个IEnumerator引用,此方法可通过IEnumerable接口的实现代码来获得,但这是可选的。
2)调用所返回的IEnumerator接口的MoveNext()方法。
3)如果MoveNext()方法返回true,就是用IEnumerator接口的Current属性获取对象的一个引用,用于foreach循环。
4)重复前面两步,知道MoveNext()方法返回false为止,此时循环停止
所以,为了在类中进行这些操作,必须重写几个方法,跟踪索引,维护Current属性,以及执行其他一些操作。
一个较为简单的替代方法是使用迭代器,它是一个代码块,按顺序提供了要在foreach循环中使用的所有值。一般情况下,这个代码块是一个方法,但也可以使用属性访问器和其他代码块作为迭代器。
1)如果要迭代一个类,可使用方法GetEnumerator(),其返回类型是IEnmerator
2)如果要迭代一个类成员,例如一个方法,则使用IEnumerable
在迭代器块中,使用yield关键字选择要在foreach循环中使用的值,以下举例:
public static IEnumerable SimpleList()
{
yield return "string 1";
yield return "string 2";
yield return "string 3";
}
public static void test()
{
foreach(string item in SimpleList())
{
Console.WriteLine(item);
}
Console.ReadKey();
}
SimpleList()就是迭代器块,迭代器块内的返回类型必须一致,否则出现错误类型转换异常。
在遇到迭代器中yield break;这个语句时,迭代器处理立即中断。
浅复制与深复制
浅显的来说,浅复制类似于引用类型,深复制类似于值类型。
浅复制是指源对象和复制对象共用一份实体,仅仅是引用的变量不同,相当于复制了一个快捷方式。
深复制是指源对象和复制对象相互独立,改变其中一个对象不会对另一个造成印象,相当于复制了文件本身。
MemberwiseClone 方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。深复制,即实现ICloneable接口.ICloneable可用于深复制和浅复制。
举例说明:
public class Content
{
public int Val;
}
浅复制(shallow copy)
public class ShallowCopy
{
public Content myContent = new Content();
public ShallowCopy(int newVal)
{
myContent.Val = newVal;
}
public object GetCopy()
{
return MemberwiseClone();
}
}
深复制(deep copy)
public class DeepCopy:ICloneable
{
public Content myContent = new Content();
public DeepCopy(int newVal)
{
myContent.Val = newVal;
}
public object Clone()
{
DeepCopy Cloner = new DeepCopy(myContent.Val);
return Cloner;
}
}
C#入门经典(第五版)学习笔记(四)的更多相关文章
- Docker技术入门与实战 第二版-学习笔记-10-Docker Machine 项目-2-driver
1>使用的driver 1〉generic 使用带有SSH的现有VM/主机创建机器. 如果你使用的是机器不直接支持的provider,或者希望导入现有主机以允许Docker Machine进行管 ...
- Docker技术入门与实战 第二版-学习笔记-8-网络功能network-3-容器访问控制和自定义网桥
1)容器访问控制 容器的访问控制,主要通过 Linux 上的 iptables防火墙来进行管理和实现. iptables是 Linux 上默认的防火墙软件,在大部分发行版中都自带. 容器访问外部网络 ...
- 《c#入门经典第五版》简介及pdf电子书网盘下载地址(收藏)
<C#入门经典(第5版)>全面讲解C# 2010和.net架构编程知识,为您编写卓越C# 2010程序奠定坚实基础.C#入门经典系列是屡获殊荣的C#名著和超级畅销书.最新版的<C#入 ...
- Docker技术入门与实战 第二版-学习笔记-10-Docker Machine 项目-1-cli
Docker Machine 是 Docker 官方编排(Orchestration)项目之一,负责在多种平台上快速安装 Docker 环境 Docker Machine是一种工具,它允许你在虚拟主机 ...
- Docker技术入门与实战 第二版-学习笔记-5-容器-命令及限制内存与cpu资源
1.启动容器 启动容器有两种方式: 基于镜像新建一个容器并启动 将在终止状态(stopped)的容器重新启动 1)新建并启动——docker run 比如在启动ubuntu:14.04容器,并输出“H ...
- C++Primer第五版学习笔记
<C++ Primer>Learning Note 程序实例下载地址:http://www.informit.com/title/0321714113 第一章 开始 ...
- Docker技术入门与实战 第二版-学习笔记-9-Docker Compose 项目-1-举例说明
Docker Compose 是 Docker 官方编排(Orchestration)项目之一,负责快速在集群中部署分布式应用 Compose 通过一个配置文件来管理多个Docker容器,在配置文件中 ...
- Docker技术入门与实战 第二版-学习笔记-6-仓库
仓库(Repository)是集中存放镜像的地方 一个容易混淆的概念是注册服务器(Registry). 实际上注册服务器是管理仓库的具体服务器,每个服务器上可以有多个仓库,而每个仓库下面有多个镜像. ...
- Docker技术入门与实战 第二版-学习笔记-7-数据管理(volume)
Docker 数据管理 为什么要进行数据管理呢?因为当我们在使用container时,可能会在里面创建一些数据或文件,但是当我们停掉或删除这个容器时,这些数据或文件也会同样被删除,这是我们并不想看见的 ...
- Docker技术入门与实战 第二版-学习笔记-2-镜像构建
3.利用 commit 理解镜像构成 在之前的例子中,我们所使用的都是来自于 Docker Hub 的镜像. 直接使用这些镜像是可以满足一定的需求,而当这些镜像无法直接满足需求时,我们就需要定制这些镜 ...
随机推荐
- 14.5.5 Deadlocks in InnoDB
14.5.5 Deadlocks in InnoDB 14.5.5.1 An InnoDB Deadlock Example 14.5.5.2 Deadlock Detection and Rollb ...
- 【转】linux 中dd命令使用详解
原文网址:http://xiaozhuang.blog.51cto.com/4396589/850657 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究 ...
- 登录MD5加盐处理
一:解决方案资源管理器截图: 二:operatorDAL.cs代码 using System; using System.Collections.Generic; using System.Linq; ...
- 游戏开发设计模式之状态模式 & 有限状态机 & c#委托事件(unity3d 示例实现)
命令模式:游戏开发设计模式之命令模式(unity3d 示例实现) 对象池模式:游戏开发设计模式之对象池模式(unity3d 示例实现) 原型模式:游戏开发设计模式之原型模式 & unity3d ...
- 【转】Markus Persson:Minecraft 游戏背后的奇才
转自酷勤网 Markus Persson是沙盒游戏Minecraft的开发者,在游戏中以Notch的名字为众多玩家所知,是游戏界绝对的巨星.美国<滚石>杂志的专栏作家David Peisn ...
- JavaScript高级程序设计5.pdf
队列方法访问规则是FIFO(First-In-First-Out,先进先出),数组方法shift()能够移除数组中第一个项并返回该项,同时将数组长度减1,结合使用shift()和push(),可以像队 ...
- 在Openstack H版部署Nova Cell 时 ,终端输入nova service-list 和 nova host-list 命令将报错
关于Cell的基本介绍,可以参考贤哥的一篇文章: [OpenStack]G版中关于Nova的Cell http://blog.csdn.net/lynn_kong/article/details/8 ...
- LaTeX手动安装宏包(package)以及生成帮助文档的整套流程
注意:版权所有,转载请注明出处. 我使用的是ctex套装,本来已经自带了许多package,但是有时候还是需要使用一些没有预装的宏包,这时就需要自己安装package了.下载package可以从CTA ...
- Div 3 - SGU 105(找规律)
分析:很容易知道序列1,2,3, 4,5, 6......与3的关系就是1,2, 0,1, 2,0,......如果是在一个数后面添加一个数就变成了这种序列1, 0, 0, 1, 0, 0, 1, 0 ...
- 回某位朋友问题备受phpcgi.exe煎熬现在cpu跑满(解决方案)
(本文原创,但是cgi参数参考一个大神写的针对小服务器的,希望大家积极投票哦) 下面是对php-cgi.ext过多引起服务器cup%的解决方法,希望对大家有帮助;大多数情况是发生在第四项上; 解决 ...