16.1 更多集合接口

集合类(这里指IEnumerable层次结构)实现的接口层次结构




16.1.1 IList<T>与IDictionary<TKey,TValue>

字典类一般只按照键进行索引,而不按位置索引。
列表“键”总是一个整数,“键集”总是从0开始的非负整数的一个连续集合。
解决数据存储或数据获取问题时,考虑 ], list[6]);

  • list.Remove("Grumpy");


  • 16.2.3 搜索List<T>

    要在 List<T> 查找特定的元素,可以使用 Contains() 、 IndexOf() 、 LastIndexOf() 和 BinarySerch() 方法。
       BinarySerch() 采用的是快得多的二分搜索算法,但要求元素已经排序好。一个有用的功能是假如元素没找到,会返回一个负整数。该值的按位取反(~)结果是”大于被查找元素的下一个元素“的索引,如果没有更大的值,则是元素的总数。这样就可以在特定位置方便插入新值。
    1. List<string> list = new List<string>();

    2. int search;

    3. list.Add("public");

    4. list.Add("protected");

    5. list.Add("private");

    6. list.Sort();

    7. search = list.BinarySearch("protected internal");

    8. if (search < 0)

    9. {

    10. list.Insert(~search, "protected internal");

    11. }

    12. foreach (string accessModifier in list)

    13. {

    14. Console.WriteLine(accessModifier);

    15. }


    高级主题:使用 FindAll() 查找多个数据项

       FindAll() 获取 Predicate<T> 类型的一个参数,它是对称为“委托”的一个方法的引用
    1. public static void Main()

    2. {

    3. List<int> list = new List<int>();

    4. list.Add(1);

    5. list.Add(2);

    6. list.Add(3);

    7. list.Add(2);

    8. list.Add(4);

    9. List<int> results = list.FindAll(Even);

    10. foreach (int number in results)

    11. {

    12. Console.WriteLine(number);

    13. }

    14. //2,2,4

    15. Console.Read();

    16. }

    17. public static bool Even(int value)

    18. {

    19. return (value % 2) == 0;

    20. }


    传递一个委托实例 Even() 。若整数实参值是偶数,就返回 true 。

    16.2.4 字典集合:Dictonary<TKey,TValue>

    和列表集合不同,字典类存储是“名称/值”对。
     插入元素,一个选择是使用 Add() 方法。
    1. Dictionary<Guid, string> dictionary =

    2. new Dictionary<Guid, string>();

    3. Guid key = Guid.NewGuid();

    4. dictionary.Add(key, "object");

    还有个选择是索引操作符

    1. Dictionary<Guid, string> dictionary =

    2. new Dictionary<Guid, string>();

    3. Guid key = Guid.NewGuid();

    4. dictionary[key] = "object";

    5. dictionary[key] = "byte";

    由于键和值都要添加到字典中,所以用于枚举字典中的元素的 foreach 循环的循环变量必须是 KeyValuePair<TKey,TValue> 。

    1. Dictionary<string, string> dictionary = new

    2. Dictionary<string, string>();

    3. int index = 0;

    4. dictionary.Add(index++.ToString(), "object");

    5. dictionary.Add(index++.ToString(), "byte");

    6. dictionary.Add(index++.ToString(), "uint");

    7. dictionary.Add(index++.ToString(), "ulong");

    8. dictionary.Add(index++.ToString(), "float");

    9. dictionary.Add(index++.ToString(), "char");

    10. dictionary.Add(index++.ToString(), "bool");

    11. dictionary.Add(index++.ToString(), "ushort");

    12. dictionary.Add(index++.ToString(), "decimal");

    13. dictionary.Add(index++.ToString(), "int");

    14. dictionary.Add(index++.ToString(), "sbyte");

    15. dictionary.Add(index++.ToString(), "short");

    16. dictionary.Add(index++.ToString(), "long");

    17. dictionary.Add(index++.ToString(), "void");

    18. dictionary.Add(index++.ToString(), "double");

    19. dictionary.Add(index++.ToString(), "string");

    20. Console.WriteLine("Key  Value    Hashcode");

    21. Console.WriteLine("---  -------  --------");

    22. foreach (KeyValuePair<string, string> i in dictionary)

    23. {

    24. Console.WriteLine("{0,-5}{1,-9}{2}",

    25. i.Key, i.Value, i.Key.GetHashCode());

    26. }

     如果只处理字典中的键或值,那么可以用 Keys 和 Values 属性。这些属性返回的数据类型是 ICollection<T> 。他们返回的是对原始字典集合中的数据的引用,而不是返回的副本。


    16.2.5 已排序集合:SortedDictionary<TKey,TValue>和SortedList<T>

    已排序集合类的元素是已经排好序的。具体说对于 SortedDictionary<TKey,TValye> 元素是按照键排序的;对于 SortedList<T> ,元素是按照值排序的(还有一个非泛型的  SortedList 实现)。

    1. SortedDictionary<string, string> sortedDictionary =

    2. new SortedDictionary<string, string>();

    3. int index = 0;

    4. sortedDictionary.Add(index++.ToString(), "object");

    5. sortedDictionary.Add(index++.ToString(), "byte");

    6. sortedDictionary.Add(index++.ToString(), "uint");

    7. sortedDictionary.Add(index++.ToString(), "ulong");

    8. sortedDictionary.Add(index++.ToString(), "float");

    9. sortedDictionary.Add(index++.ToString(), "char");

    10. sortedDictionary.Add(index++.ToString(), "bool");

    11. sortedDictionary.Add(index++.ToString(), "ushort");

    12. sortedDictionary.Add(index++.ToString(), "decimal");

    13. sortedDictionary.Add(index++.ToString(), "int");

    14. sortedDictionary.Add(index++.ToString(), "sbyte");

    15. sortedDictionary.Add(index++.ToString(), "short");

    16. sortedDictionary.Add(index++.ToString(), "long");

    17. sortedDictionary.Add(index++.ToString(), "void");

    18. sortedDictionary.Add(index++.ToString(), "double");

    19. sortedDictionary.Add(index++.ToString(), "string");

    20. Console.WriteLine("Key  Value    Hashcode");

    21. Console.WriteLine("---  -------  ----------");

    22. foreach (

    23. KeyValuePair<string, string> i in sortedDictionary)

    24. {

    25. Console.WriteLine("{0,-5}{1,-9}{2}",

    26. i.Key, i.Value, i.Key.GetHashCode());

    27. }


     键中元素采用的是字幕顺序,而不是数值顺序,这是由于键是字符串,而不是整数。
    在一个已排序的字典集合中插入或删除元素时,由于要保持集合中的元素顺序,所以相对前面的 Dictionary<TKey,TValue> 执行事件要稍微长一些。它内部使用两个数组,一个用于键的检索,一个勇于索引的检索。
    对于 System.Collections.Sorted 排序列表,索引操作是通过 GetByIndex() 和 SetByIndex() 方法来支持的。
    对于 System.Collections.Generic.SortedList<TKey,TValue> ,Keys 和 Values 属性分别返回 IList<TKey> 和 IList<TValue> 实例。这些方法使得已排序列表具有字典行为,也有列表类型的集合的行为。

    16.2.6 栈集合:Stack<T>

    栈集合被设计为:后进先出
    两个方法:
    Push():插入元素。
    Pop():按照与添加时相反的顺序获取并删除元素。
     为了不修改栈的前提下访问栈中的元素,使用 Peek() 和 Contains() 方法。
     Peek() :返回 Pop() 将获取的下一个元素。
     Contains() :勇于判断一个元素是否存在于栈的某个地方。

    16.2.7队列集合:Queue<T>

    队列集合类和栈集合类基本相同,遵循先入先出模式
     Enqueue() :入队
     Dequeue() :出队。
    队列集合根据需要自动增大。但缩小时不一定回收之前使用的存储空间,因为这会使插入新元素的动作变得很昂贵。如果确定队列长时间大小不变,可以使用 TrimToSize() 方法提醒队列集合你希望回收存储空间。

    16.2.8 链表:LinkedList<T>

     链表允许正向和反向遍历。(没有对应的非泛型类型)

    16.4 返回null或者空集合

    返回数组或集合时,必须允许返回 null ,或者返回不包含任何数据的集合实例。
    通常,返回没有数据的集合实例是更好的选择,可避免遍历集合数据前检查 null 值。
    但是这个准则也有例外,比如 null 被有意的用来表示有别于“零个项目”的情况。
    例如,网站用户名集合可能会是 null ,以此来表示出于某种原因未获得最新集合。

    16.5 迭代器

    本节讨论利用迭代器为自定义集合实现自己的 IEnumerator<T> 、 IEnumerable<T> 和对应的非泛型接口。
       加入某个类希望支持 foreach 进行迭代,就必须实现枚举器( enumerator )模式。

    16.5.1 迭代器定义

    迭代器是实现类的方法的一个途径,是更加复杂的枚举数模式的语法简化形式。由于在生成的CIL代码中仍然采用枚举数模式,所以并不会带来真正的运行时性能优势。不过,使用迭代器而不是手动实现枚举数模式,能显著提高程序员的编程效率。

    16.5.2 迭代器语法

    迭代器提供了迭代器接口(也就是 IEnumerator<T> 和 IEnumerable<T> 的组合)的一个快捷实现。
    创建一个 GetEnumerator() 方法,表示声明了一个迭代器。接着要添加对迭代器接口的支持
    1. public IEnumerator<T> GetEnumerator()

    2. {

    3. //...

    4. return new List<T>.Enumerator();//This will be implimented in 16.16

    5. }


    16.1.3 从迭代器生成值

    迭代器类似于函数,但它不返(renturn)值,而是生成(yield)一系列值。
    未完待续。。。





    《C#本质论》读书笔记(16)构建自定义集合的更多相关文章

    1. 十六、C# 常用集合类及构建自定义集合(使用迭代器)

      常用集合类及构建自定义集合 1.更多集合接口:IList<T>.IDictionary<TKey,TValue>.IComparable<T>.ICollectio ...

    2. 16位模式/32位模式下PUSH指令探究——《x86汇编语言:从实模式到保护模式》读书笔记16

      一.Intel 32 位处理器的工作模式 如上图所示,Intel 32 位处理器有3种工作模式. (1)实模式:工作方式相当于一个8086 (2)保护模式:提供支持多任务环境的工作方式,建立保护机制 ...

    3. Node.js高级编程读书笔记 - 4 构建Web应用程序

      Outline 5 构建Web应用程序 5.1 构建和使用HTTP中间件 5.2 用Express.js创建Web应用程序 5.3 使用Socket.IO创建通用的实时Web应用程序 5 构建Web应 ...

    4. 《java并发编程实战》读书笔记11--构建自定义的同步工具,条件队列,Condition,AQS

      第14章 构建自定义的同步工具 本章将介绍实现状态依赖性的各种选择,以及在使用平台提供的状态依赖机制时需要遵守的各项规则. 14.1 状态依赖性的管理 对于并发对象上依赖状态的方法,虽然有时候在前提条 ...

    5. ArcGIS API for JavaScript 4.2学习笔记[16] 弹窗自定义功能按钮及为要素自定义按钮(第五章完结)

      这节对Popups这一章的最后两个例子进行介绍和解析. 第一个[Popup Actions]介绍了弹窗中如何自定义工具按钮(名为actions),以PopupTemplate+FeatureLayer ...

    6. OCA读书笔记(16) - 执行数据库恢复

      16. Performing Database Recovery 确定执行恢复的必要性访问不同接口(EM以及命令行)描述和使用可用选项,如RMAN和Data Recovery Advisor执行恢复- ...

    7. 流处理与消息队列------《Designing Data-Intensive Applications》读书笔记16

      上一篇聊了聊批处理的缺点,对于无界数据来说,流处理会是更好的选择,"流"指的是随着时间的推移逐步增加的数据.消息队列可以将这些流组织起来,快速的在应用程序中给予反馈.但是消息队列与 ...

    8. 《Java Concurrency》读书笔记,构建线程安全应用程序

      1. 什么是线程安全性 调用一个函数(假设该函数是正确的)操作某对象常常会使该对象暂时陷入不可用的状态(通常称为不稳定状态),等到操作完全结束,该对象才会重新回到完全可用的状态.如果其他线程企图访问一 ...

    9. 【读书笔记】构建之法(CH4~CH6)

      从chapter4至chapter6,围绕着构建过程的合作讨论构建之法,而合作与个人工作的区别却以一个微妙的问题为开端:阅读别人的代码有多难? 两人合作:(驾驶员与领航员) 合作要注意代码风格规范与设 ...

    随机推荐

    1. Fiddler 抓包工具总结

      阅读目录 1. Fiddler 抓包简介 1). 字段说明 2). Statistics 请求的性能数据分析 3). Inspectors 查看数据内容 4). AutoResponder 允许拦截制 ...

    2. 为网站文字前面添加图标 在线调用 Font Awesome 字体icon小图标 美化网站

      一.如何开始 1.将下面的代码复制粘贴到HTML页面面的 <head> 下面 <link rel="stylesheet" href="https:// ...

    3. 【BZOJ-2730】矿场搭建 Tarjan 双连通分量

      2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1602  Solved: 751[Submit][Statu ...

    4. POJ2417 Discrete Logging

      本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

    5. COGS439. [网络流24题] 软件补丁

      [问题描述] 对于一个软件公司来说,在发行一个新软件之后,可以说已经完成了工作.但是实际上,许多软件公司在发行一个新产品之后,还经常发送补丁程序,修改原产品中的错误(当然,有些补丁是要收费的). 如某 ...

    6. python 下 tinker、matplotlib 混合编程示例一个

      该例是实现了 Tinker 嵌入 matplotlib 所绘制的蜡烛图(k 线),数据是从 csv 读入的.花一下午做的,还很粗糙,仅供参考.python 代码如下: import matplotli ...

    7. 【Beta】七天屠蛟记

      团队名字: 一不小心就火了 屠龙天团少年们: 031402504 陈逸超 (组长) 031402505 陈少铭 031402511 黄家俊 031402515 翁祖航 031402516 黄瑞钰 03 ...

    8. 6种php发送get、post请求的方法简明归纳与示例

      方法1: 用file_get_contents 以get方式获取内容: <?php $url='http://www.jb51.net/'; $html = file_get_contents( ...

    9. js字符串方法

      字符串方法根据下标返回字符:str.charAt()//传入一个下标返回字符str.charCodeAt();// 传入一个下标获取编码String.formCharCode();//接受编码,编码转 ...

    10. AE开发使用内存图层

      AE开发中,有时需要从磁盘中读取一些文件信息如坐标点转为图层并进行分析,此过程并不需要坐标点入库之类的操作,就可以创建一个内存图层解决问题.创建内存图层需要用到InMemoryWorkspaceFac ...