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.pswp.cn/news/209127.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/209127.shtml
英文地址,請注明出處:http://en.pswp.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…