《C#入门经典 第7版》读书笔记_集合
目录
1.ArrayList
构造函数
实现的接口
ArrayList和简单数组中的元素
ArrayList的基本功能 (增, 删, 插)
2.自定义集合
CollectionBase类
索引器
3.键控集合和IDictionary
集合与数组:
使用数组创建包含许多对象或值的数据类型. 但是数组有一个最大的限制是一旦创建好数组, 它的大小不能改变.
C#中的数组是实现System.Array的实例, 他们只是集合类(Collection Class)中的一种类型.
System.Collections命名空间中的几个接口提供了基本集合功能:
- IEnumerable可以迭代集合中的项.
- IDictionary(继承于IEnumerable和ICollection)提供了可通过键值访问的项列表.
- IList(继承于IEnumerable和ICollection)提供了集合的项列表, 允许访问这些项, 并提供一些其他与项列表相关的基本功能.
- ICollection(继承于IEnumerable)可以获取集合中项的个数, 并且将项复制到一个简单的数组类型中.
1.ArrayList
ArrayList也实现了IEnumerable, ICollection和IList接口. 虽然底层是数组, 但是大小可变.
-
构造函数
ArrayList有三个构造函数, 除了无参构造函数, 还有两个构造函数. 第一个把一个现有的集合作为参数, 将其中的内容复制到新的实例中. 另一个构造函数的参数是一个int类型, 可以指定集合的容量. 这个不是绝对容量, 因为如果超出了这个容量, 集合的容量就会增加一倍.
// ArrayList的三种构造函数
public ArrayList();
public ArrayList(ICollection c); // 将实现ICollection的任何对象都可以复制到新的实例中
public ArrayList(int capacity);// 可以指定一个初始的容量
-
实现的接口
ArrayList也实现了IEnumerable接口, 所以可以使用foreach进行遍历. 实现了ICollection接口, 可以使用Count属性.
ArrayList中可以同时存储引用类型和值类型.
-
ArrayList和简单数组中的元素
简单数组中的元素是强类型化的, 可以直接访问它们所包含的项类型. 所以可以直接调用项的方法.
ArrayList集合是System.Object对象的集合(通过多态性赋给具体的对象), 所以必须对所有的项进行类型转换.
-
ArrayList的基本功能 (增, 删, 插)
ArrayList可以删除其中的元素Remove(), RemoveAt(), RemoveRange(). 使用序号的操作, 基本上都是实现于IList接口.
// ArrayList中的删除功能, 可以重写
public virtual void Remove(Object object);
public virtual void RemoveAt(int index);// 删除指定序号的项
public virtual void RemoveRange(int index, int count);// index 起始序号 count 删除个数, 可以为0
删除ArrayList中的元素后, 集合中的元素个数-1, 删除元素后的所有元素序号也-1. 所以在删除操作之后要注意元素的序号发生改变.
ArrayList可以在末尾添加元素Add(), AddRange()
public virtual void Add(Object object);// 在末尾添加指定元素
public virtual void AddRange(ICollection c);// 在末尾添加实现了ICollection接口对象的所有元素
在指定位置添加元素Insert(), InsertRange()
public virtual void Insert(int index, Object? value);// 指定位置添加元素
public virtual void InsertRange(int index, ICollection c);// 指定位置添加实现ICollection接口对象的所有元素
2.自定义集合
-
CollectionBase类
创建System.Collections.CollectionBase的派生类, 这个抽象类提供了集合类的大量实现代码.
CollectionBase提供两个受保护的属性List和InnerList, 它们可以访问存储对象本身. List可以通过IList接口访问项, InnerList则是存储项的ArrayList对象.
// 通过派生CollectionBase 实现自建的强类型化的集合类
namespace Ex01
{public abstract class Animal{}// 继承了CollectionBase 这个类是一个集合类public class Animals : CollectionBase{// 通过IList接口中的Add方法实现自定义的Add方法 这个是强类型化操作public void Add(Animal newAnimal) => List.Add(newAnimal);// Remove同上public void Remove(Animal oldAnimal) => List.Remove(oldAnimal);}// Animal派生类Cowpublic class Cow : Animal{}class program{static void Main(string[] args){Animal animalCollection = new Animal(); animalCollection.Add(new Cow());// CollectionBase的派生类可以使用foreach遍历, 如果没有使用索引符不能使用序号foreach (Animal animal in animalCollection){Console.WriteLine(animal.ToString()); }} }
}
-
索引器
索引器是一种特殊的属性.返回的项需要进行类型转换, 因为IList.List属性返回的是一个Object类型的对象.
public class Animals : CollectionBase
{...// 索引器是一种特殊的属性public Animal this[int animalIndex]{// List -> IList接口访问CollectionBase中的ArrayList// IList.List返回的是一个Object类型的对象 要进行类型转换get { return (Animal)List[animalIndex]; }set { List[animalIndex] = value; } }
}
3.键控集合和IDictionary
实现IDictionary接口, 允许项通过键值索引. C#提供了一个基类DictionaryBase简化了IDictionary接口的实现, 用法与CollectionBase类似.
使用foreach遍历Dictionary需要使用DictionaryEntry. DictionaryEntry是一个结构体, 包含一个key和一个value, 表示一个键值对.
public class Animals : DictionaryBase
{// Dictionary是继承DictionaryBase的一个IDictionary接口public void Add(string animalID, Animal newAnimal) => Dictionary.Add(animalID, 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; } }
}class program
{static void Main(string[] args){Animals animalDic = new Animals();animalDic.Add("001", new Animal());animalDic.Add("002", new Animal());// foreach遍历Dictionary需要用到DictionaryEntryforeach (DictionaryEntry de in animalDic){// DictionaryEntry的value是Object的对象, 需要类型转换WriteLine(((Animal)de.value).Name); } }
}