C#8.0本质论第十七章--构建自定义集合

C#8.0本质论第十七章–构建自定义集合

17.1更多集合接口

17.1.1IList< T >和IDictionary< TKey , TValue >

这两个接口决定了集合类型是侧重于通过位置索引来获取值,还是侧重于通过键来获取值。

实现这两个接口的类都必须提供索引器。

17.1.2ICollection< T >

IList< T >和IDictionary< TKey , TValue >都实现了ICollection< T >

17.2主要集合类

17.2.1列表集合:List< T >

List< T >类的性质和数组相似,关键区别就是随着元素增多,这种类会自动扩展。此外,列表可通过显示调用TrimToSize()或Capacity来缩小。

**IComparable< T >和IComparer< T >**的区别很细微,却很重要。前者说“我知道如何将我自己和我的类型的另一个实例进行比较”,后者说“我知道如何比较给定类型的两个实例”。

using System;
using System.Collections.Generic;
// ...
public class Contact
{public string FirstName { get; private set; }public string LastName { get; private set; }public Contact(string firstName, string lastName){this.FirstName = firstName;this.LastName = lastName;}
}
public class NameComparison : IComparer<Contact>
{public int Compare(Contact? x, Contact? y){if(Object.ReferenceEquals(x, y))return 0;if(x == null)return 1;if(y == null)return -1;int result = StringCompare(x.LastName, y.LastName);if(result == 0)result = StringCompare(x.FirstName, y.FirstName);return result;}private static int StringCompare(string? x, string? y){if(Object.ReferenceEquals(x, y))return 0;if(x == null)return 1;if(y == null)return -1;return x.CompareTo(y);}
}
17.2.2全序

实现IComparable< T >和IComparer< T >时必须生成一个全序(total order),必须为任何可能的数据项排列组合提供一致的排序结果。例如上面代码中连实参是null的情况都考虑到了,不能任何一个元素为null就返回0,否则可能出现两个非null元素等于null但不相等的情况。

17.2.3搜索List< T >

可以使用Contains(),Indexof(),LastIndexOf()和BinarySearch()方法。

BinarySearch()要求有序,如果没有找到,会返回一个负整数。该值的取反结果是“大于被查找元素的下一个元素”的索引。没有更大的则是元素总数。

17.2.4字典集合:Dictionary< TKey , TValue >

可利用Keys和Values属性只处理字典类中的键或值。返回ICollection< T >类型,返回的是对原始字典集合中的数据的引用,而不是返回拷贝。

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

元素是按照键排序的

17.2.6栈集合:Stack< T >
17.2.7队列集合:Queue< T >
17.2.8链表:LinkedList< T >

链表集合,允许正向和反向遍历。(所以是双向链表)

17.3提供索引器

数组,字典和列表都提供了索引器(indexer)以便根据键或索引来获取/设置成员。

interface IPair<T>
{T First { get; }T Second { get; }T this[PairItem index] { get; }
}public enum PairItem
{First,Second
}public struct Pair<T> : IPair<T>
{public Pair(T first, T second){First = first;Second = second;}public T First { get; }public T Second { get; }public T this[PairItem index]{get{switch (index){case PairItem.First:return First;case PairItem.Second:return Second;default:throw new NotImplementedException($"The enum { index.ToString() } has not been implemented");}}}
}

索引器的声明和属性很相似,但不是使用属性名,而是使用关键字this,后跟方括号中的参数列表。主题也像属性,有get和set块。索引可获得多个参数,甚至可以重载。

17.4返回null或者空集合

返回数组和集合时允许返回null,更好的选择是返回不含任何数据项的集合实例。可避免强迫调用者在便利集合前检查null值。

17.5迭代器

本节讨论如何利用迭代器(iterator)为自定义集合实现自己的IEnumerator< T >,IEnumerable< T >和对应的非泛型接口。迭代器使集合的用户能遍历集合的内部结构,同时不必了解结构的内部实现。

类要支持用foreach进行迭代,就必须实现枚举数(enumerator)模式,如第15章所述,C#的foreach循环结构被编译器扩展成while循环结构,它以从IEnumerable< T >接口获取的IEnumerator< T >接口为基础。

17.5.1定义迭代器
17.5.2迭代器语法

迭代器提供了迭代器接口(IEnumerable< T >和IEnumerator< T >)的一个快捷实现。

using System.Collections;
using System.Collections.Generic;public class BinaryTree<T> : IEnumerable<T>
{public BinaryTree(T value){Value = value;}#region IEnumerable<T>public IEnumerator<T> GetEnumerator(){// ...}#endregion IEnumerable<T>public T Value { get; }public Pair<BinaryTree<T>> SubItems { get; set; }
}public struct Pair<T>
{public Pair(T first, T second) : this(){First = first;Second = second;}public T First { get; }public T Second { get; }
}

要为GetEnumerator()提供一个实现。

17.5.3从迭代器生成值

迭代器类似于函数,但它不是返回(return)一个值,而是**生成(yield)**一系列值。

每次迭代器遇到yield return语句都生成一个值,之后控制立即回到请求数据项的调用者。当调用者请求下一项时,慧紧接着在上一个yield return语句之后执行。

17.5.4迭代器和状态

GetEnumerator()在foreach语句中被首次调用时,慧创建一个迭代器对象,其状态被初始化为特殊的“起始”状态,表示迭代器尚未执行代码,所以尚未生成任何值。

只要foreach继续,迭代器就会一直持续其状态。循环每一次请求下一个值,控制就会一直维持其状态。循环每一次请求下一个值,控制就会进入迭代器,从上一次离开的位置继续。该位置是根据迭代器对象中存储的状态信息来判断的。foreach终止,迭代器的状态就不再保存了。

17.5.5更多的迭代器例子
17.5.6将yield return语句放到循环中
17.5.7取消更多的迭代:yield break

可以使用yield break使MoveNext()返回false,使控制立即回到调用者并终止循环。

C#编译器遇到一个迭代器时,会根据枚举数模式将代码展开成恰当的CIL,在生成的CIL代码中,C#编译器首先创建一个嵌套的私有类来实现IEnumerator< T >接口,以及它的Current熟悉和MoveNext()方法。Current属性返回与迭代器的返回类型对应的一个类型。

using System;
using System.Collections;
using System.Collections.Generic;
// ...[NullableContext(1)][Nullable(0)]public struct Pair<[Nullable(2)] T> : IPair<T>, IEnumerable<T>, IEnumerable{public Pair(T first, T second){First = first;Second = second;}public T First { get; }public T Second { get; }public T this[PairItem index]{get{PairItem pairItem = index;PairItem pairItem2 = pairItem;T result;if (pairItem2 != PairItem.First){if (pairItem2 != PairItem.Second){throw new NotImplementedException(string.Format("The enum {0} has not been implemented", index.ToString()));}result = Second;}else{result = First;}return result;}}public IEnumerator<T> GetEnumerator(){yield return First;yield return Second;yield break;}IEnumerator IEnumerable.GetEnumerator(){return GetEnumerator();}}
}

yield关键字是上下文关键字,不是保留关键字。所以可以合法地声明名为yield的局部变量。

事实上,C#1.0之后加入的所有关键字都是上下文关键字,这是为了防止升级老程序来使用语言的新版本时出问题。

17.5.8在一个类中创建多个迭代器
17.5.9yield语句的要求

只有在返回IEnumerator< T >或者IEnumerable< T >类型的成员中,才能使用yield return语句。

主体包含yield return语句的成员不能包含简单return语句。

yield语句只能在方法,用户自定义操作符或者索引器/属性的get访问器方法中出现。成员不可获取任何ref或者out参数。

yield语句不能在匿名方法或Lambda表达式中出现。

yield语句不能在try语句的catch和finally块中出现。此外,yield语句在try块中出现的前提是没有catch块。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/209127.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在线教育小程序正在成为教育行业的新生力量

教育数字化转型是目前教育领域的一个热门话题&#xff0c;那么到底什么是教育数字化转型&#xff1f;如何做好教育数字化转型&#xff1f; 教育数字化转型是利用信息技术和数字工具改变和优化教育的过程。主要特征包括技术整合、在线学习、个性化学习、大数据分析、云计算、虚拟…

【C++学习手札】基于红黑树封装模拟实现map和set

​ &#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 &#x1f49c;本文前置知识&#xff1a; 红黑树 ♈️今日夜电波&#xff1a;漂流—菅原纱由理 2:55━━━━━━️&#x1f49f;──────── 4:29 …

Appium获取toast方法封装

一、前置说明 toast消失的很快&#xff0c;并且通过uiautomatorviewer也不能获取到它的定位信息&#xff0c;如下图&#xff1a; 二、操作步骤 toast的class name值为android.widget.Toast&#xff0c;虽然toast消失的很快&#xff0c;但是它终究是在Dom结构中出现过&…

【计算机网络】HTTP请求

目录 前言 HTTP请求报文格式 一. 请求行 HTTP请求方法 GET和POST的区别 URL 二. 请求头 常见的Header 常见的额请求体数据类型 三. 请求体 结束语 前言 HTTP是应用层的一个协议。实际我们访问一个网页&#xff0c;都会像该网页的服务器发送HTTP请求&#xff0c;服务…

使用Java将图片添加到Excel的几种方式

1、超链接 使用POI&#xff0c;依赖如下 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependency>Java代码如下,运行该程序它会在桌面创建ImageLinks.xlsx文件。 …

GPT-4V 在机器人领域的应用

在科技的浩渺宇宙中&#xff0c;OpenAI如一颗璀璨的星辰&#xff0c;于2023年9月25日&#xff0c;以一种全新的方式&#xff0c;向世界揭示了其最新的人工智能力作——GPT-4V模型。这次升级&#xff0c;为其旗下的聊天机器人ChatGPT装配了语音和图像的新功能&#xff0c;使得用…

『Linux升级路』进度条小程序

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;Linux &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、预备知识 &#x1f4d2;1.1缓冲区 &#x1f4d2;1.2回车和换行 二、倒计…

修改正点原子综合实验的NES模拟器按键控制加横屏

​​​​​​​ 开发板&#xff1a;stm32f407探索者开发板V2 屏幕是4.3寸-800-480-MCU屏 手头没有V3开发板&#xff0c;只有V2&#xff0c;所以没法测试 所以只讲修改哪里&#xff0c;请自行修改 先改手柄部分&#xff0c;把手柄改成按键 找到左边的nes文件夹中的nes_mai…

采用轨到轨输出设计 LTC6363HMS8-2、LTC6363HMS8-1、LTC6363HRD、LTC6363IDCB差分放大器I

产品详情 LTC6363 系列包括四个全差分、低功耗、低噪声放大器&#xff0c;具有经优化的轨到轨输出以驱动 SAR ADC。LTC6363 是一款独立的差分放大器&#xff0c;通常使用四个外部电阻设置其增益。LTC6363-0.5、LTC6363-1 和 LTC6363-2 都有内部匹配电阻&#xff0c;可分别创建…

【Python百宝箱】代码冲突?文件合并不再是问题!Python解决方案大揭秘

Python脚本与图形工具&#xff1a;文件比较与合并的完整指南 前言 在软件开发、版本控制和数据处理领域&#xff0c;文件比较和合并是至关重要的任务。Python生态系统中涌现了许多强大的工具和库&#xff0c;为开发者提供了丰富的选择。本指南将深入探讨 Python 中常用的文件…

看完了一个动画电影-心灵奇旅

refer: 开二倍速看完了&#xff0c;一部分是听的&#xff0c;剧情还可以&#xff0c;就是普通的治愈片。 里边有个台词&#xff1a; 一条小鱼游到一条老鱼旁边说,“我要找到他们称之为海洋的东西。” “海洋?”老鱼问,“你现在就在海洋里啊。” “这儿?”小鱼说,“这儿是水…

人工智能:走向未来的智慧之路

1. 定义与范畴 人工智能&#xff08;AI&#xff09;是一门研究如何使计算机系统能够模拟人类智慧的科学与技术。这包括了机器学习、深度学习、自然语言处理、计算机视觉等多个子领域。机器学习让计算机能够通过数据学习&#xff0c;而深度学习则通过模拟人脑神经网络的方式实现…

C++数据结构:B树

目录 一. 常见的搜索结构 二. B树的概念 三. B树节点的插入和遍历 3.1 插入B树节点 3.2 B树遍历 四. B树和B*树 4.1 B树 4.2 B*树 五. B树索引原理 5.1 索引概述 5.2 MyISAM 5.3 InnoDB 六. 总结 一. 常见的搜索结构 表示1为在实际软件开发项目中&#xff0c;常用…

博途PLC SCL间接寻址编程应用

这篇博客里我们将要学习Pointer和Any指针&#xff0c;PEEK和POKE指令&#xff0c;当然我们还可以数组类型数据实现数组指针寻址&#xff0c;具体应用介绍请参考下面文章链接&#xff1a; https://rxxw-control.blog.csdn.net/article/details/134761364https://rxxw-control.b…

一文讲解如何从 Clickhouse 迁移数据至 DolphinDB

ClickHouse 是 Yandex 公司于2016年开源的 OLAP 列式数据库管理系统&#xff0c;主要用于 WEB 流量分析。凭借面向列式存储、支持数据压缩、完备的 DBMS 功能、多核心并行处理的特点&#xff0c;ClickHouse 被广泛应用于广告流量、移动分析、网站分析等领域。 DolphinDB 是一款…

【Hadoop_02】Hadoop运行模式

1、Hadoop的scp与rsync命令&#xff08;1&#xff09;本地运行模式&#xff08;2&#xff09;完全分布式搭建【1】利用102将102的文件推到103【2】利用103将102的文件拉到103【3】利用103将102的文件拉到104 &#xff08;3&#xff09;rsync命令&#xff08;4&#xff09;xsync…

使用 HTML 地标角色提高可访问性

请务必确保所有用户都可以访问您的网站&#xff0c;包括使用屏幕阅读器等辅助技术的用户。 一种方法是使用 ARIA 地标角色来帮助屏幕阅读器用户轻松浏览您的网站。使用地标角色还有其他好处&#xff0c;例如改进 HTML 的语义并更轻松地设置网站样式。在这篇博文中&#xff0c;我…

深度探索Linux操作系统 —— 构建initramfs

系列文章目录 深度探索Linux操作系统 —— 编译过程分析 深度探索Linux操作系统 —— 构建工具链 深度探索Linux操作系统 —— 构建内核 深度探索Linux操作系统 —— 构建initramfs 文章目录 系列文章目录前言一、为什么需要 initramfs二、initramfs原理探讨三、构建基本的init…

tomcat篇---第二篇

系列文章目录 文章目录 系列文章目录前言一、tomcat容器是如何创建servlet类实例?用到了什么原理?二、tomcat 如何优化?三、熟悉tomcat的哪些配置?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女…

Web应用JSON数据保护(密码算法、密钥、数字签名和数据加密)

1.JSON&#xff08;JavaScript Object Notation&#xff09; JSON是一种轻量级的数据交换格式&#xff0c;采用完全独立于编程语言的文本格式来存储和表示数据。JSON通过简单的key-value键值对来描述数据&#xff0c;可以被广泛用于网络通信、数据存储等各种应用场景&#xff0…