C#集合

集合可以容纳和检索一系列的元素。

迭代器

迭代器提供了一组方法,用来访问集合中的元素。

在.NET中,迭代器被称作枚举器。

.NET中各种集合都实现了迭代器,用来访问集合中的元素。

迭代器相关接口

    //表示类型是可枚举的。
    public interface IEnumerable
    {
        //获取枚举器
        IEnumerator GetEnumerator();
    }

    //表示类型是可枚举的。返回的枚举器是泛型的。
    public interface IEnumerable<out T> : IEnumerable
    {
        //获取泛型枚举器。
        IEnumerator<T> GetEnumerator();
    }

    //表达枚举器,支持对集合进行迭代。
    public interface IEnumerator
    {
        //获取枚举器位于当前位置的元素。
        Object Current { get; }

        //将枚举器移动到集合的下一个元素,成功返回true。
        Boolean MoveNext();

        //将枚举器设置为其初始位置。
        void Reset();
    }


    //表示泛型的枚举器。
    public interface IEnumerator<out T> : IDisposable, IEnumerator
    {
        //获取枚举器位于当前位置的元素。
        T Current { get; }
    }

集合类型实现IEnumerable可枚举接口,IEnumerable接口方法GetEnumerator用来返回迭代器。

注意:迭代器的Reset方法是一个错误的设计,因为并不是所有的集合都支持重置位置。如果要重新迭代,可以通过GetEnumerator方法获取一个新的迭代器。

实现枚举器的接口,支持使用foreach支持迭代。

List<int> list = new List<int>{1,2,3,4,5};

foreach(int item in list)
{
    Console.WriteLine(item);
}

在内部,foreach调用的就是迭代器。

List<int> list = new List<int>{1,2,3,4,5};

IEnumerator enumerator = list.GetEnumerator();
int item = 0;

while(enumerator.MoveNext())
{
    item = enumerator.Current;
    Console.WriteLine(item);
}

在迭代器内部,不能修改集合,否则会报异常。

列表

列表和数组相似,可以容纳多个元素。不同的是,空间可以动态扩展。

泛型列表

System.Collections.Generic.List<T>是一个泛型的列表。和数组相似,可以容纳多个元素。不同的是,空间可以动态扩展。

List<int> list = new List<int>();
list.Add(100);
list.Add(200);
int i = list[0];
int j = list[1];
list[1] = 500;

在内部,列表也是使用数组,在数组空间不够使创建新数组,并保留已有的值。

集合初始化

List<int> list = new List<int>
{
    100,200
}

集合也可以向数组一样初始化。在内部,也是调用了Add方法。

泛型列表常用方法

void Add(T item)。向列表添加元素。

void RemoveAt(int index)。删除列表指定索引的元素。

void Clear()。清空列表的元素。

T this[int index]{get;set}。获取或写入元素。

int IndexOf(T item),int LastIndexOf(T item)。查找元素出现位置。

列表的特点

List<T>在末尾添加,删除很快,但是在其他位置添加删除比较慢,支持索引读写。

其他列表

System.Collections.ArrayList。非泛型列表,兼容旧代码使用。

LinkList<T>使用链表的方式来实现的列表。在任何地方添加,删除都很快,但是不支持按索引读写。

Stack<T>栈,访问受限的列表,只支持添加,删除,访问顶部。

Queue<T>队列,访问受限的列表,只支持添加到尾部,删除和访问头部。

字典

字典是一系列键值对,其中的键不能重复,并且提供高效的按键检索。也被叫做哈希表。

泛型字典

System.Collections.Generic.Dictionary<TKey,TValue>是泛型字典。

Dictionary<string,string> dict = new Dictionary<string,string>();
dict["cat"] = "猫";
dict["dog"] = "狗";
Console.WriteLine(dict["cat"]);

字典初始化

Dictionary<string,string> dict = new Dictionary<string,string>
{
    {"cat","猫"},
    {"dog","狗"}
}

字典的初始化也是调用了Add方法。

索引器初始化(C#6.0)

Dictionary<string,string> dict = new Dictionary<string,string>
{
    ["cat"]="猫",
    ["dog"]="狗"
}

泛型字典的常用方法

Dictionary(IComparer<TKey> comparer)。构造字典时支持设置简单比较器。

int Count{get;}。获取字典键值对的个数。

bool ContainsKey(TKey key)。判断指定键是否存在于字典。

TValue this[TKey key]{get;set;}。根据键获取或设置值。获取时如果不存在,会报KeyNotFoundException;设置时会覆盖已有值。

bool TryGetValue(TKey key,out TValue value)。尝试根据键获取值。

void Add(TKey key,TValue value)。添加一个键值对。

bool Remove(TKey key)。删除指定键的键值对。

void Clear()。清空指定键值对。

字典的特点

字典添加,删除,按照键检索很快。

字典键的要求

字典的键需要正确的实现Equals方法和GetHashCode方法。必须保证Equalstrue的两个对象的GetHashCode结果一致。

如果有字段影响Equals,GetHashCode的结果,并且可以被外界改变,那么在被添加到字典之后,不能修改这些字段,否则会查找错误。

其他字典

非泛型字典System.Collections.Hashtable。仅仅兼容旧代码时使用。

SortedDictioonary<TKey,TValue>。按照键排序的字典。

SortedList<TKey,TValue>。按照键进行排序的键/值对的集合。可以按照索引访问键和值。

集相当于只有键的字典。集就是数学上的集合,不能重复,集之间的关系和集里面元素的顺序无关。

泛型集

System.Collections.Generic.HashSet<T>

其他的集

System.Collections.Generic.SortedSet<T>。按照键排序的集。

集合相关接口

System.Collections.Generic.IEnumerable<T>。表示类型是可枚举的。可枚举的类型可以通过foreach获取所有元素。

System.Collections.Generic.ICollection<T>。表示基本集合方法,包括添加,删除,清空,获得数量。

System.Collections.Generic.IList<T>。表示基本的列表方法,包括按照位置索引,按照位置插入,按照位置删除。

System.Collections.Generic.IDictionary<TKey, TValue>。基本的字典方法,包括添加键值对,按照键查找,按照键删除,按照键读写,尝试按照键获取值。

System.Collections.Generic.ISet<T>。基本的集的方法,包含集之间的关系操作。

其他集合类

System.Collections.ObjectModel.Collection<T>。表示基本的列表类型。自定义列表可以将其作为基类。

System.Collections.ObjectModel.ReadOnlyCollection<T>。表示只读的集合。

System.Collections.ObjectModel.ObservableCollection<T>。可在删除,添加时提供通知的集合。

System.Collections.Specialized.NameValueCollection。字符串和值的字典。值可以是一个或多个字符串。

System.Collections.BitArray。表示位数组。