集合与泛型
集合
集合的功能可以通过实现System.Collections
名称空间中的接口来实现,所以我们不仅可以使用基本集合类,例如:System.Array
,还可以创建自己的定制集合类。优点是定制的集合类可以是强类型化的,也就是说,从集合中提取项时,不需要把它们转换为正确类型。另一个优点是可以提供专用的方法,例如,可以提供获得项子集的快捷方法。
System.Collections
名称空间中的常用接口
- IEnumerable 可以迭代集合中的项
- ICollection(继承于IEnumerable)可以获取集合中项的个数,并能把项复制到一个简单的数组类型中。
- IList(继承于IEnumerable 和 ICollection)提供了集合的项列表,允许访问这些项,并提供其他一些与项列表相关的基本功能。
- IDictionary(继承于IEnumerable 和 ICollection)类似于 IList,但提供了可通过键值(而不是索引)访问的项列表。
定义集合
既可以使用System.Array
类来定义简单集合,也可以使用System.Collections.ArrayList
类来定义复杂集合(不需要初始化其大小),这个类还有另外两个构造函数,第一个构造函数把现有的集合作为一个参数,将其内容复制到新实例中;另一个构造函数通过一个参数设置集合的容量,这个容量用一个int值指定,设置集合中可以包含的初始项数。但这并不是绝对容量,因为如果集合中的项数超过了这个值,容量就会自动增加一倍。简单数组是强类型化的,可以直接访问它们所包含的项类型。ArrayList 集合是 System.Object
对象的集合,所以必须对所有的项进行数据类型转换。ArrayList 集合可以使用 Remove() 和 RemoveAt() 方法根据项的引用或索引从数组中删除项。ArrayList 集合可以用 AddRange() 方法一次添加好几项,这个方法接受带有 ICollection 接口的任意对象。ArrayList 集合可以用 IList 接口中的 IndexOf() 方法获取某一项的索引。除此之外,我们还可以创建自己的强类型化的集合。从System.Collections.CollectionBase
类中派生,这个抽象类提供了集合类的大量实现代码。CollectionBase 提供了两个受保护的属性,它们可以访问存储的对象本身,List 可以通过 IList 接口访问项,InnerList 则是用于存储项的 ArrayList 对象。
using System;
using System.Collections;
namespace ConsoleApp1
{
public class Animals : CollectionBase
{
public void Add(Animal newAnimal)
{
List.Add(newAnimal);
}
public void Remove(Animal oldAnimal)
{
List.Remove(oldAnimal);
}
public Animal this[int animalIndex] //索引符
{
get
{
return (Animal)List[animalIndex];
}
set
{
List[animalIndex] = value;
}
}
public Animals() { }
}
}
DictionaryBase 允许项通过键值进行索引。
using System;
using System.Collections;
namespace ConsoleApp1
{
public class Animals : DictionaryBase
{
public void Add(string newID, Animal newAnimal)
{
Dictionary.Add(newID, newAnimal);
}
public void Remove(string animalID)
{
Dictionary.Remove(animalID);
}
public Animal this[string animalID]
{
get
{
return (Animal)Dictionary[animalID];
}
set
{
Dictionary[animalID] = value;
}
}
public Animals() { }
}
}
基于DictionaryBase的集合和基于CollectionBase 的集合之间的一个区别是 foreach 的工作方式。
foreach (DictionaryEntry myEntry in animalCollection)
{
Console.WriteLine($"{((Animal)myEntry.Value).Name} : {myEntry.Value.ToString()}");
}
解决方法是实现一个迭代器。
迭代器
迭代器的定义是,它是一个代码块,按顺序提供了要在 foreach 块中使用的所有值。一般情况下,这个代码块是一个方法,但也可以使用属性访问器和其他代码块作为迭代器。如果要迭代一个类,可使用方法GetEnumerator(),其返回类型是IEnumerator;如果要迭代一个类成员,其返回类型是IEnumerable。在迭代器块中,使用yield关键字选择要在foreach循环中使用的值。其语法如下:
yield return <value>;
在Animals类中添加下面代码:
public new IEnumerator GetEnumerator()
{
foreach(object animal in Dictionary.Values)
{
yield return (Animal)animal;
}
}
现在就可以使用 foreach 循环来迭代集合中的 Animal 对象了。
比较
对象之间的两类比较:类型比较,值比较。
类型比较
is 运算符
is 运算符用来检查对象是不是给定类型,或者是否可以转换为给定类型,如果是,这个运算符就返回 true。
值比较
转换
泛型
泛型的含义
泛型类是以实例化过程中提供的类型或类为基础建立的,可以毫不费力地对对象进行强类型化。System.Collections.Generic
名称空间中包含的泛型集合类型有:List<T>,Dictionary<K, V>
。