亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

C#集合 -- Equality和Order插件

2019-11-17 03:04:12
字體:
來源:轉載
供稿:網友

C#集合 -- Equality和Order插件

在前面的文章C#相等性比較和C#排序比較中,我已經敘述了類型相等,類型哈希,和類型比較的.NET標準協議。實現了這些協議的類型在一個字典或者列表中也可以正常工作。但是需要注意的是:

  • 只有當類型的Equals方法和GetHashCode方法返回有意義的結果時,該類型才可以作為Dictionary或Hashtable的鍵
  • 只有當類型實現了IComparable/IComparable<T>才可以作為排序字典或排序列表的鍵

一個類型的默認相等實現或比較實現典型地反映了該類型最“自然”的那一面。但是,有時候,默認的行為并不是你期望的效果。你可能希望一個string類型的鍵可以區分大小寫;或者你希望一個可排序的客戶列表按照客戶的郵政編碼排序。由于這些原因,.NET Framework定義了一組對應的插入協議,該協議可以實現下面兩個目的:

  • 允許你在可替代的相等性行為或可替代的比較行為之間相互切換
  • 允許你使用一個字典或一個排序集合,它們的鍵的類型內在是不等的或不可比較的

這些協議由下面的接口組成:

IEqualiyComparer和IEqualityComparer<T>

  • 執行插件式相等性比較和哈希
  • 可被Hashtable和Dictionary識別

IComparer和IComparer<T>

  • 執行插件式排序比較
  • 可被排序字典或拍戲集合,以及Array.Sort識別

每個接口都有generic和非generic的版本。IEqualityComparer接口也包含了EqualityComparer的默認的實現。

此外,在Framework 4.0中,還引入了兩個新的接口IStructuralEquatable和IStructuralComparable,它們允許結構可以像類或者數組那樣執行比較。

IEqualityComparer和EqualityComparer

image

相等性比較在非默認的相等性和哈希行為上切換,這主要適用于Dictionary類和HashTable類。

回憶一下以哈希表為基礎的字典,對于一個指定的鍵,需要回答下面兩個問題:

  • 該鍵與其他的鍵是否相同?
  • 該鍵的哈希碼是多少?

實現IEqualityComparer的相等性比較器可以回答上面兩個問題

public interface IEqualityComparer<T>{bool Equals (T x, T y);int GetHashCode (T obj);}public interface IEqualityComparer // Nongeneric version{bool Equals (object x, object y);int GetHashCode (object obj);}

為了創建一個自定義比較器,你需要實現上面一個或者兩個接口(如果實現了上面連個接口,那么就可以保證最大程度的互操作)。但這么做優點單調,另外一種替換方法是為抽象類EqualityComparer類創建子類,EqualityComparer的定義如下:

public abstract class EqualityComparer<T> : IEqualityComparer,IEqualityComparer<T>{public abstract bool Equals (T x, T y);public abstract int GetHashCode (T obj);bool IEqualityComparer.Equals (object x, object y);int IEqualityComparer.GetHashCode (object obj);public static EqualityComparer<T> Default { get; }}

由于EqualityComparer實現連個兩個接口,因此你的工作就簡化為重寫它的兩個抽象方法。

Equals方法和GetHashCode與我們在C#相等性比較中所敘述的一樣。在下面的例子中,我們定義一個Customer類,它包含兩個成員,然后創建一個相等性比較器以比較客戶的姓名是否相等。

public class Customer{public string LastName;public string FirstName;public Customer (string last, string first){LastName = last;FirstName = first;}}public class LastFirstEqComparer : EqualityComparer <Customer>{public override bool Equals (Customer x, Customer y){return x.LastName == y.LastName && x.FirstName == y.FirstName;}public override int GetHashCode (Customer obj){return (obj.LastName + ";" + obj.FirstName).GetHashCode();}}

為了演示器可以工作,我們創建兩個客戶實例

Customer c1 = new Customer ("Bloggs", "Joe");Customer c2 = new Customer ("Bloggs", "Joe");

由于我們沒有重寫object.Equals,在執行比較時,會執行常規的引用類型比較

Console.WriteLine (c1 == c2); // FalseConsole.WriteLine (c1.Equals (c2)); // False

如果我們創建一個客戶字典實例,且使用默認的相等性比較器對這兩個客戶進行比較,那么會返回false

var d = new Dictionary<Customer, string>();d [c1] = "Joe";Console.WriteLine (d.ContainsKey (c2)); // False

最后,如果我們在創建字典實例時,在構造函數中指定了自定義相等性比較

var eqComparer = new LastFirstEqComparer();var d = new Dictionary<Customer, string> (eqComparer);d [c1] = "Joe";Console.WriteLine (d.ContainsKey (c2)); // True

EqualityComparer<T>.Default

調用EqualityComparer<T>.Default返回一個generic的相等性比較器,使用這個比較器可以替代靜態的object.Equals方法。使用這種方式的優點在于,它首先檢查類型T是否實現了IEquatble<T>;如果它實現了這個接口,那么就就調用該實現,從而避免了額外的裝箱操作。這特別適用于generic的方法:

static bool Foo<T> (T x, T y){bool same = EqualityComparer<T>.Default.Equals (x, y);...}

IComparer和Comparer

image

對于排序字典和集合,比較器還經常用于替代自定義排序。

請注意,比較器對于非排序字典和哈希表沒有作用,這位非排序字典和哈希表需要IEqualityComperer去獲取哈希碼。類似地,一個相等性比較器在排序字典和集合中也不會有用。

下面是IComparer接口的定義

public interface IComparer{int Compare(object x, object y);}public interface IComparer <in T>{int Compare(T x, T y);}

如果,你要使用相等性比較,你可以繼承抽象類Comparer<T>,而不是實現ICompare接口或/和ICompare<T>接口。

public abstract class Comparer<T> : IComparer, IComparer<T>{public static Comparer<T> Default { get; }public abstract int Compare (T x, T y); // Implemented by youint IComparer.Compare (object x, object y); // Implemented for you}

下面的列子演示了一個類wish,一個比較器通過wish類的PRipority屬性進行排序

class Wish{public string Name;public int Priority;public Wish (string name, int priority){Name = name;Priority = priority;}}class PriorityComparer : Comparer <Wish>{public override int Compare (Wish x, Wish y){if (object.Equals (x, y)) return 0; // Fail-safe checkreturn x.Priority.CompareTo (y.Priority);}}

調用object.Equals方法確保了我們的比較結果不會與Equals方法矛盾。在上面的例子中,調用靜態方法object.Equals方法比調用x.Equals方法好,這是因為x可能是null。

下面的代碼演示了如何使用PriorityComparer來排序一個列表

var wishList = new List<Wish>();wishList.Add (new Wish ("Peace", 2));wishList.Add (new Wish ("Wealth", 3));wishList.Add (new Wish ("Love", 2));wishList.Add (new Wish ("3 more wishes", 1));wishList.Sort (new PriorityComparer());foreach (Wish w in wishList) Console.Write (w.Name + " | ");// OUTPUT: 3 more wishes | Love | Peace | Wealth |

在下面的例子中,SurnameComparer允許你對電話簿列表的聯系人數據按照姓進行排序

class SurnameComparer : Comparer <string>{string Normalize (string s){s = s.Trim().ToUpper();if (s.StartsWith ("MC")) s = "MAC" + s.Substring (2);return s;}public override int Compare (string x, string y){return Normalize (x).CompareTo (Normalize (y));}}var dic = new SortedDictionary<string,string> (new SurnameComparer());dic.Add ("MacPhail", "second!");dic.Add ("MacWilliam", "third!");dic.Add ("McDonald", "first!");foreach (string s in dic.Values)Console.Write (s + " "); // first! second! third!

StringComparer

image

StringComparer是一個預定義的插件式類,用于字符串的相等性比較和排序比較,并允許你指定語言和是否區分大小寫。StringComparer實現了IEqualityComparer和IComparer接口(以及它們的Generic類型接口)。因此,它可以用于任何類型的字典或者排序集合。它的定義如下

public abstract class StringComparer : IComparer, IComparer <string>,IEqualityComparer,IEqualityComparer <string>{public abstract int Compare (string x, string y);public abstract bool Equals (string x, string y);public abstract int GetHashCode (string obj);public static StringComparer Create (CultureInfo culture,bool ignoreCase);public static StringComparer CurrentCulture { get; }public static StringComparer CurrentCultureIgnoreCase { get; }public static StringComparer InvariantCulture { get; }public static StringComparer InvariantCultureIgnoreCase { get; }public static StringComparer Ordinal { get; }public static StringComparer OrdinalIgnoreCase { get; }}

由于StringComparer是抽象類,所以你需要通過它的靜態方法或屬性獲取實例。StringComparer.Ordinal是字符串相等性比較的默認行為;StringComparer.CurrentCulture是字符串排序的默認行為。

在下面的例子中,創建了一個有序的區分大小寫的字典,因為dict[“Joe”]和dict[“JOE”]是相等的

var dict = new Dictionary<string, int> (StringComparer.OrdinalIgnoreCase);

在下面的例子中,名字數組使用澳洲英語排序

string[] names = { "Tom", "HARRY", "sheila" };CultureInfo ci = new CultureInfo ("en-AU");Array.Sort<string> (names, StringComparer.Create (ci, false));

最后一個例子則是區分文化的SurnameComparer

class SurnameComparer : Comparer <string>{StringComparer strCmp;public SurnameComparer (CultureInfo ci){// Create a case-sensitive, culture-sensitive string comparerstrCmp = StringComparer.Create (ci, false);}string Normalize (string s){s = s.Trim();if (s.ToUpper().StartsWith ("MC")) s = "MAC" + s.Substring (2);return s;}public override int Compare (string x, string y){//
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品视频9999| 精品欧美国产一区二区三区| 国产精品久久久久久久午夜| 中日韩午夜理伦电影免费| 国产视频精品va久久久久久| 狠狠色香婷婷久久亚洲精品| 精品少妇v888av| 欧美性理论片在线观看片免费| 97精品欧美一区二区三区| 国产精品一区二区久久| 国内免费久久久久久久久久久| 国产亚洲综合久久| 国产精品久久色| 欧美黑人巨大精品一区二区| 久久亚洲一区二区三区四区五区高| 日韩欧美精品中文字幕| 亚洲成人a级网| 欧美高清在线视频观看不卡| 成人黄色在线免费| 亚洲国产另类 国产精品国产免费| 亚洲视频一区二区三区| 国产精品国产亚洲伊人久久| 国产精品日韩电影| 中文字幕一区二区精品| 日韩精品日韩在线观看| 米奇精品一区二区三区在线观看| 538国产精品一区二区在线| 久久精品成人一区二区三区| 久久精品99久久久香蕉| 亚洲人成绝费网站色www| 日韩国产中文字幕| 日韩动漫免费观看电视剧高清| 欧美亚洲一区在线| 91久久精品久久国产性色也91| 国产免费一区二区三区香蕉精| 亚洲国产精品一区二区三区| 欧美老少做受xxxx高潮| 亚洲福利影片在线| 欧美在线www| 成人免费淫片视频软件| 中文字幕精品av| 亚洲国产一区二区三区在线观看| 久久久免费精品| 国产日本欧美一区二区三区在线| 国产91网红主播在线观看| 日韩中文在线中文网在线观看| 日韩电视剧在线观看免费网站| 亚洲欧美日韩精品久久| 国产suv精品一区二区| 亚洲欧洲午夜一线一品| 久久综合国产精品台湾中文娱乐网| 色偷偷综合社区| 欧美日韩亚洲一区二区| 日韩美女中文字幕| 久久久久国产精品免费| 亚洲va欧美va国产综合久久| 91九色国产社区在线观看| 国产综合久久久久| 欧美激情久久久| 成人免费视频xnxx.com| 亚洲黄色在线观看| 国产欧美精品一区二区三区介绍| 国产精品视频在线观看| 中文字幕视频一区二区在线有码| 精品国偷自产在线视频99| 国产suv精品一区二区| 日韩精品中文字幕视频在线| 国产午夜精品一区理论片飘花| 欧美成人网在线| 日韩亚洲国产中文字幕| 亚洲欧美日本精品| 日韩电影中文字幕在线| 波霸ol色综合久久| 亚洲v日韩v综合v精品v| 欧美午夜片在线免费观看| 欧美午夜视频在线观看| 久久久精品视频成人| 宅男66日本亚洲欧美视频| 欧美日韩另类字幕中文| 成人黄在线观看| 国产精品久久久久久久久久东京| 亚洲福利影片在线| 伊人久久久久久久久久| 亚洲自拍偷拍网址| 欧美成人午夜激情视频| 九九热精品视频在线播放| 午夜精品美女自拍福到在线| 一区二区三区视频免费在线观看| 日韩在线视频免费观看高清中文| 这里只有精品久久| 91chinesevideo永久地址| 国产精品成人品| 国产精品18久久久久久首页狼| 一个人看的www欧美| 国产精品7m视频| 欧美一区二区.| 欧美日韩国产成人高清视频| 亚洲午夜久久久久久久| 日韩欧美第一页| 色噜噜狠狠色综合网图区| 欧美日韩国产成人| 国产精品日韩av| 日韩午夜在线视频| 中文国产成人精品久久一| 精品少妇v888av| 伊是香蕉大人久久| 欧美性开放视频| 国产一区二区三区18| 久久伊人精品一区二区三区| 亚洲欧美日韩直播| 中文字幕日韩综合av| 91夜夜未满十八勿入爽爽影院| 在线精品播放av| 狠狠爱在线视频一区| 91精品综合视频| 日韩中文字幕免费看| 日韩小视频网址| 欧美精品成人在线| 国产精品成人va在线观看| 色樱桃影院亚洲精品影院| 神马久久桃色视频| 国产成人一区二区三区电影| 亚洲国产成人精品久久久国产成人一区| 国产精品91久久| 中文字幕亚洲欧美一区二区三区| 久久精品视频在线播放| 这里只有视频精品| 久久精品视频网站| 国产成人精品视频在线观看| 欧美激情综合色综合啪啪五月| 日韩av网址在线观看| 97国产精品久久| 国内精品在线一区| 欧美激情在线观看视频| 久久精视频免费在线久久完整在线看| 中文字幕精品在线| 欧美电影免费观看高清完整| 26uuu另类亚洲欧美日本一| 成人久久久久久久| 国产午夜精品久久久| 色偷偷av一区二区三区| 欧美不卡视频一区发布| 中文字幕综合一区| 久久久极品av| 欧洲精品久久久| 自拍偷拍免费精品| 久久99青青精品免费观看| 亚洲精品国产综合区久久久久久久| 日韩成人在线视频网站| 国产欧美婷婷中文| 蜜臀久久99精品久久久无需会员| 欧美插天视频在线播放| 精品国产乱码久久久久久虫虫漫画| 国产成人小视频在线观看| 亚洲老司机av| 亚洲国产成人久久| 欧美日韩中文字幕| 欧美性猛交丰臀xxxxx网站| 4p变态网欧美系列| 5566日本婷婷色中文字幕97| 国产成人高清激情视频在线观看| 亚洲va男人天堂| 亚洲美女性生活视频| 亚洲欧美日韩在线高清直播|