比較和排序(IComparable和IComparer以及它們的泛型實現)(轉)

来源:http://www.cnblogs.com/25miao/archive/2017/08/13/7354016.html
-Advertisement-
Play Games

C#筆記25:比較和排序(IComparable和IComparer以及它們的泛型實現) 本文摘要: 1:比較和排序的概念; 2:IComparable和IComparer; 3:IComparable和IComparer的泛型實現IComparable<T>和IComparer<T>; 1:比較和 ...


C#筆記25:比較和排序(IComparable和IComparer以及它們的泛型實現)

本文摘要:

1:比較和排序的概念;

2:IComparable和IComparer;

3:IComparable和IComparer的泛型實現IComparable<T>和IComparer<T>;

 

1:比較和排序的概念

    比較:兩個實體類之間按>,=,<進行比較。

    排序:在集合類中,對集合類中的實體進行排序。排序基於的演算法基於實體類提供的比較函數。

    基本型別都提供了預設的比較演算法,如string提供了按字母進行比較,int提供了按整數大小進行比較。

 

2:IComparable和IComparer

    當我們創建了自己的實體類,如Student,預設想要對其按照年齡進行排序,則需要為實體類實現IComparable介面。

class Student:IComparable
    {
        public string Name { get; set; }
        public int Age { get; set; }

        #region IComparable Members

        public int CompareTo(object obj)
        {
            Student student = obj as Student;
            if (Age > student.Age)
            {
                return 1;
            }
            else if (Age == student.Age)
            {
                return 0;
            }
            else
            {
                return -1;
            }
            //return Age.CompareTo(student.Age);
        }
        #endregion
    }
    PS:註意上面代碼中CompareTo方法有一條註釋的代碼,其實本函數完全可以使用該註釋代碼代替,因為利用了整形的預設比較方法。此處未使用本註釋代碼,是為了更好的說明比較器的工作原理。
    接下來寫一個測試用例:

public Form1()
        {
            InitializeComponent();
            studentList = new ArrayList();
            studentList.Add(new Student() { Age = 1, Name = "a1" });
            studentList.Add(new Student() { Age = 5, Name = "g1" });
            studentList.Add(new Student() { Age = 4, Name = "b1" });
            studentList.Add(new Student() { Age = 2, Name = "f1" });
        }
        ArrayList studentList;
        private void button1_Click(object sender, EventArgs e)
        {
            studentList.Sort();
            foreach (Student item in studentList)
            {                
                this.textBox1.Text += item.Name + "----" +item.Age.ToString() + "\r\n"  ;
            }
        }

運行結果:

a1----1
f1----2
b1----4
g1----5

      OK,疑問來了。如果不想使用年齡作為比較器了,那怎麼辦。這個時候IComparer的作用就來了,可使用IComparer來實現一個自定義的比較器。如下:

 

class SortName: IComparer
    {
        #region IComparer Members

        public int Compare(object x, object y)
        {
            Student s1 = x as Student;
            Student s2 = y as Student;
            return s1.Name.CompareTo(s2.Name);
        }

        #endregion
    }

這個時候,我們在排序的使用為Sort方法提供此比較器:

      studentList.Sort(new SortName());

      運行的結果是:

a1----1
b1----4
f1----2
g1----5

            

3:IComparable和IComparer的泛型實現IComparable<T>和IComparer<T>

      如果我們稍有經驗,我們就會發現上面的代碼我們使用了一個已經不建議使用的集合類ArrayList。當泛型出來後,所有非泛型集合類已經建議不儘量使用了。至於原因,從上面的代碼中我們也可以看出一點端倪。

      註意查看這個Compare函數,如:

 

public int Compare(object x, object y)
        {
            Student s1 = x as Student;
            Student s2 = y as Student;
            return s1.Name.CompareTo(s2.Name);
        }

我們發現這個函數進行了裝箱和拆箱。而這是會影響性能的。如果我們的集合中有成千上萬個複雜的實體對象,則在排序的時候所耗費掉的性能就是客觀的。而泛型的出現,就可以避免掉拆箱和裝箱。

      故上文代碼中的ArrayList,應該換成List<T>,對應的,我們就該實現IComparable<T>和IComparer<T>。最終的代碼應該像:

 

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            studentList = new List<Student>();
            studentList.Add(new Student() { Age = 1, Name = "a1" });
            studentList.Add(new Student() { Age = 5, Name = "g1" });
            studentList.Add(new Student() { Age = 4, Name = "b1" });
            studentList.Add(new Student() { Age = 2, Name = "f1" });
        }
        List<Student> studentList;
        private void button1_Click(object sender, EventArgs e)
        {
            studentList.Sort(new SortName());

            foreach (Student item in studentList)
            {
                
                this.textBox1.Text += item.Name + "----" +item.Age.ToString() + "\r\n"  ;
            }
        }
    }

    class Student:IComparable<Student>
    {
        public string Name { get; set; }
        public int Age { get; set; }

        #region IComparable<Student> Members

        public int CompareTo(Student other)
        {
            return Age.CompareTo(other.Age);
        }

        #endregion
    }

    class SortName: IComparer<Student>
    {
        #region IComparer<Student> Members

        public int Compare(Student x, Student y)
        {
            return x.Name.CompareTo(y.Name);
        }

        #endregion
    }

 


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

-Advertisement-
Play Games
更多相關文章
  • Azure 1 月新發佈:Microsoft Power BI Embedded 公共預覽和電腦視覺 API 標準版的更新以及 Azure IoT 網關 SDK 和中心設備管理新功能正式發佈以及關於計量名稱變更的通知 ...
  • 網關,物聯網網關 Azure 物聯網平臺可以按需運作,整合現有設備和服務,讓開發者利用自己熟悉的編程語言進行擴展,無縫整合企業部署的後端平臺。而隨著 Azure 物聯網網關 SDK(Software Development Kit)的進一步優化,用戶甚至可以將 Azure 數據中心外的物聯網和高級分... ...
  • CentOS 調教方法: ①刪除虛擬機但保留磁碟,隨後將系統盤作為數據盤掛載到臨時虛擬機上 ②修改配置文件 /etc/sysconfig/network-scripts/ifcfg-eth0 ③將虛擬網卡硬體地址改成正確的值,或刪除該行 ④保存並退出,分離該磁碟,並基於該磁碟新建虛擬機 SUSE... ...
  • Azure 12 月新發佈:導入/導出服務,虛擬機和雲服務的 Av2,虛擬網路對等互連現已正式發佈以及流分析的更新 ...
  • 共用訪問簽名是一種字元串,包含可附加到 URI 的安全令牌,可以讓我們委派對象的訪問許可權,並指定訪問的許可權和日期/時間範圍等限制。例如我們可以授予對 Blob、容器、隊列、文件和表的訪問許可權。很多服務在做驗證時都會用到 SAS,例如 Azure Service Bus、Azure IoT Hub 等... ...
  • 上篇講了 "《asp.net core在linux上的環境部署》" 。今天我們將做幾個小玩意實戰一下。用到的技術和工具有mysql、websocket、AngleSharp(爬蟲html解析)、nginx多站點部署。 NO1 留言板(mysql的使用) 演示:http://haojima.net 這 ...
  • 推薦網站:http://blog.csdn.net/zhuyu19911016520/article/category/6318590 ...
  • 目的: 擴展 C# WinForm 自帶的表格控制項,使其可以自動判斷數據的上下界限值,並標識溢出。 這裡使用的方法是:擴展 表格的列 對象:DataGridViewColumn。 1.創建類:DecimalCheckCell 2.創建類:DecimalCheckColumn 3.現在就可以使用了,在 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...