IList,ICollection,IEnumerable,IEnumerator,IQueryable

来源:http://www.cnblogs.com/yyzyou/archive/2017/12/02/7955285.html
-Advertisement-
Play Games

http://www.cnblogs.com/edison1105/archive/2012/07/30/2616082.html 1、首先看一個簡單的例子 大家都知道要實現foreach的必須要實現IEnumerable和IEnumerator的介面,只有實現了它們,才能實現遍歷,所以要講fore ...


http://www.cnblogs.com/edison1105/archive/2012/07/30/2616082.html

 

1、首先看一個簡單的例子

int[] myArray = { 1, 32, 43, 343 };
            IEnumerator myie = myArray.GetEnumerator();
            myie.Reset();
            while (myie.MoveNext())
            {
                int i = (int)myie.Current;
                Console.WriteLine("Value: {0}", i);
            }
相信很多人都不會像上面這樣去遍歷myArray這個數組,通常我們這樣會這樣做
            foreach (int item in myArray)
                Console.WriteLine(item.ToString());

在大部分的情況下,很多人會使用for和foreach來遍曆數組,而對於上面的語法卻用的很少,但是對foreach的具體來歷還很模糊!


2、理解foreach

大家都知道要實現foreach的必須要實現IEnumerable和IEnumerator的介面,只有實現了它們,才能實現遍歷,所以要講foreach的來歷,必須要把那兩個介面給搞清楚點!

這邊也想說明一點的是:如果對這兩個介面有了一定的瞭解後,只要實現那個GetEnumerator方法即可,而不需要實現於IEnumerable介面,這隻是針對對這兩個介面有一定瞭解的朋友!

 

2.1 IEnumerable

 

具體的作用:就是使實現這個介面的對象成為可枚舉類型。

 

IEnumerable介面包含一個GetEnumerator方法,返回值為IEnumerator的類型!代碼如下:

    public class MyColors : IEnumerable
    {
        string[] colors = { "Red", "Yellow", "Biue" };
        public IEnumerator GetEnumerator()
        {
            return colors.GetEnumerator();
        }
    }

那麼我們在客戶端進行調用的時候就可以這樣做了!

            MyColors colors = new MyColors();
            foreach (string item in colors)
                Console.WriteLine(item);
這樣就能使用實現這個介面的對象進行foreach遍歷了,就是這麼簡單的一個列子,這邊可能有的人會有疑問,我們就實現了IEnumerable介面但卻沒實現IEnumerator介面,可是我們不是說只有實現了這兩個介面才可以進行foreach遍歷嗎?可以這樣說當使用forach進行遍歷的時候,編譯器會到這個對象的類中去尋找GetEnumerator方法,找到這個方法後返回這個一個IEnumerator的對象(枚舉數),而我這邊返回的是“colors.GetEnumerator()”,是一個數組對象調用它本身中的“GetEnumerator”方法,所以說數組本身就實現了IEnumerator介面,那麼兩個介面都實現了,不就好實現foreach遍歷了,其實在實現遍歷枚舉數的時候編譯器會自動去調用數組中實現枚舉數的類中的方法。

2.2  IEnumerator

介面的作用:實現可枚舉數,首先看一下介面的定義:

 

QQ截圖20120730230335

 

包含一個屬性兩個方法

MoveNext → 把當前的項移動到下一項(類似於索引值),返回一個bool值,這個bool值用來檢查當前項是否超出了枚舉數的範圍!

 

Current → 獲取當前項的值,返回一個object的類型(這邊會涉及到裝箱和拆箱的問題 → 後面講泛型的時候會涉及到)!

 

Reset → 顧名思義也就是把一些值恢復為預設值,比如把當前項恢復到預設狀態值!

    public class MyIEnumerator : IEnumerator
    {
        public MyIEnumerator(string[] colors)
        {
            this.colors = new string[colors.Length];
            for (int i = 0; i < this.colors.Length; i++)
                this.colors[i] = colors[i];
        }

       string[] colors;        //定義一個數組,用來存儲數據

        int position = -1;      //定義當前項的預設值,也就是索引值,一開始認識數組的索引從“0”開始,
        //怎麼預設設置他為“-1”呢,最後才想明白,這樣設置是合情合理的!

        public object Current       //根據當前項獲取相應的值
        {
            get
            {
                return colors[position];          //返回當前項的值,但是會做一個裝箱的操作!
              }
       }

       public bool MoveNext()                  //移動到下一項
        {
          if (position < colors.Length - 1)     //這就是設置預設值為-1的根據
            {
                position++;
                return true;
          }
          else
          {
                return false;
          }
        }

        //重置當前項的值,恢復為預設值
        public void Reset()
        {
            this.position = -1;
        }
    }

上面講到的IEnumerable介面中GetEnumerator方法是獲取要遍歷的枚舉數,在我們沒有創建自己的遍歷枚舉數的類時,我們使用的是Array的遍歷枚舉數的方法(關於數組的可枚舉類型和枚舉數會在下一篇講到),但這個有的時候不一定適合我們,我們需要為自己定製一個更合適的,所以我們要創建自己的枚舉數類(也就是上面的代碼),把第三點和第四點的代碼合併起來(改動一點代碼),如下:

        public class MyColors   //: IEnumerable
        {
            string[] colors = { "Red", "Yellow", "Biue" };

            public IEnumerator GetEnumerator()
            {
                return new MyIEnumerator(colors);
            }
        }

3、關於可枚舉類型和枚舉數

①可枚舉類型 → 實現IEnumerable介面,可以不需要直接實現這個介面,但必須有個GetEnumerator方法,返回值類型必須為IEnumerator類型,也就是第四點最後一段代碼中介面註釋的那種寫法!

②枚舉數 → 實現IEnumerator介面,實現全部方法,首先是調用GetEnumerator返回一個類型為IEnumerator的枚舉數,然後編譯器會隱式的調用實現IEnumerator類中的方法和屬性!

 

總結:所以實現foreach遍歷,必須達到上面的兩種條件才能進行遍歷對象,他們可以寫在一起也可以分開,最好是分開,進行職責分離,一個類乾一件事總歸是好事!也滿足面向對象的單一指責設計原則。

 

下麵的代碼示例演示如何實現自定義集合的 IEnumerable 和 IEnumerator 介面(代碼來自MSDN)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    public class Person
    {
        public Person(string fName, string lName)
        {
            this.firstName = fName;
            this.lastName = lName;
        }

        public string firstName;
        public string lastName;
    }

    public class People : IEnumerable
    {
        private Person[] _people;
        public People(Person[] pArray)
        {
            _people = new Person[pArray.Length];

            for (int i = 0; i < pArray.Length; i++)
            {
                _people[i] = pArray[i];
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return (IEnumerator)GetEnumerator();
        }

        public PeopleEnum GetEnumerator()
        {
            return new PeopleEnum(_people);
        }
    }

    public class PeopleEnum : IEnumerator
    {
        public Person[] _people;

        // Enumerators are positioned before the first element
        // until the first MoveNext() call.
        int position = -1;

        public PeopleEnum(Person[] list)
        {
            _people = list;
        }

        public bool MoveNext()
        {
            position++;
            return (position < _people.Length);
        }

        public void Reset()
        {
            position = -1;
        }

        object IEnumerator.Current
        {
            get
            {
                return Current;
            }
        }

        public Person Current
        {
            get
            {
                try
                {
                    return _people[position];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }
            }
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            Person[] peopleArray = new Person[3]
            {
                new Person("John", "Smith"),
                new Person("Jim", "Johnson"),
                new Person("Sue", "Rabon"),
            };

            People peopleList = new People(peopleArray);
            foreach (Person p in peopleList)
                Console.WriteLine(p.firstName + " " + p.lastName);
        }
    }
}

 

無圖無真相

QQ截圖20120730223046

 

我並非標題黨,下麵介紹IList,ICollection,IQueryable

 

1、IList 是 ICollection 介面的子代,並且是所有非泛型列表的基介面。IList 實現有三種類別:只讀、固定大小和可變大小。無法修改只讀 IList。固定大小的 IList 不允許添加或移除元素,但允許修改現有元素。可變大小的 IList 允許添加、移除和修改元素。

 

2、ICollection 介面是 System.Collections 命名空間中類的基介面。ICollection 介面擴展 IEnumerable;IDictionary 和 IList 則是擴展 ICollection 的更為專用的介面。 IDictionary 實現是鍵/值對的集合,如 Hashtable 類。 IList 實現是值的集合,其成員可通過索引訪問,如 ArrayList 類。  某些集合(如 Queue 類和 Stack 類)限制對其元素的訪問,它們直接實現 ICollection 介面。  如果 IDictionary 介面和 IList 介面都不能滿足所需集合的要求,則從 ICollection 介面派生新集合類以提高靈活性。定義所有非泛型集合的大小、枚舉器和同步方法。

 

3、IQueryable 提供對未指定數據類型的特定數據源的查詢進行計算的功能,IQueryable 介面由查詢提供程式實現。 該介面只能由同時實現 IQueryable(Of T) 的提供程式實現。 如果該提供程式不實現 IQueryable(Of T),則無法對提供程式數據源使用標準查詢運算符。 IQueryable 介面繼承 IEnumerable 介面,以便在前者表示一個查詢時可以枚舉該查詢的結果。 枚舉強制執行與 IQueryable 對象關聯的表達式樹。 “執行表達式樹”的定義是查詢提供程式所特有的。 例如,它可能涉及將表達式樹轉換為適用於基礎數據源的查詢語言。 在調用 Execute 方法時將執行不返回可枚舉結果的查詢。

 

不好意思,這裡就先粗略的介紹一下了,都說我很懶了吐舌笑臉,明天還要上班,下次再續…


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近自己裝了個ubuntu kylin 在使用的過程中發現,系統的apt-get 的源有毛病,總是安裝不了軟體。 感覺應該是傳說中的牆的原因,所以準備換到阿裡雲的源。 下麵是步驟: 1、複製原文件備份 sudo cp /etc/apt/source.list /etc/apt/source.list ...
  • 我們在學習的時候使用vmware創建自己的虛擬機,但是我們有時學習環境需要多台電腦進行操作演示,如果安裝創建虛擬機、再在虛擬機上安裝操作系統、這樣很花費我們的時間,而且還步能保證服務的一直性,這就用到vmware的強大功能——克隆,廢話不多說,操作如下: 一、虛擬機克隆 1、在vmware上創建一 ...
  • 有時候我們需要修改主機的host主機名,方便管理和識別自己的伺服器,修改步驟如下: 第一步: vi /etc/hosts 正常情況下,修改了第一步就可以了,如果通過hostname命令查看還是修改以前的話,執行第二步 第二步: vi /etc/sysconfig/network 把hostname設 ...
  • 阿裡雲CentOS7.3搭建 Apache+MySQL+PHP環境 參考https://www.cnblogs.com/apro-abra/p/4862285.html 一、安裝Apache 1.安裝 yum -y install httpd yum -y install httpd yum -y ...
  • Ceph官方版本目前支持的糾刪碼很有限,實驗室這塊希望能夠整合我們自主開發的糾刪碼BRS( " B inary R eed– S olomon encoding" ),所以需要編譯Ceph環境。Ceph官方目前推薦的安裝方式都是通過Ceph deploy的工具來安裝配置,搭建起來十分簡單。目前直接通 ...
  • 1、馮洛伊曼的主要思想: (1)用二進位代碼表示程式和數據; (2)電腦採用存儲程式的工作方式; (3)電腦硬體由存儲器、運算器、控制器、輸入設備和輸出設備等五大部件組成。 2、電腦性能的定義 (1)相應時間(Response Time) 從提出請求到被執行的時間。 (2)吞吐率(Throug ...
  • 在裸板2440中,當我們使用nand啟動時,2440會自動將前4k位元組複製到內部sram中,如下圖所示: 然而此時的SDRAM、nandflash的控制時序等都還沒初始化,所以我們就只能使用前0~4095地址,在前4k地址里來初始化SDRAM,nandflash,初始化完成後,才能將nandflas ...
  • 突然發現VS2017.15.4.5 打開項目特別慢,並且生成項目時也要等上好久好久, 一直以為是vs更新的問題,輾轉半天發現是項目本身原因。 dotnet core 項目下如果出現一個文件夾內包含大量的文件,比如node_modules之類的,會影響dotnet run的運行效率, 解決辦法: cs ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...