詳解.NET 4.0數(shù)組的相關(guān)新增功能
在.NET 4.0中我們將看到數(shù)組方面有很大的改進(jìn),本文將給大家討論的是.NET 4.0數(shù)組的新增功能,希望對大家用好.NET 4.0數(shù)組有所幫助。
1 兩數(shù)組是否“相等”?
在實(shí)際開發(fā)中,有時(shí)我們需要比對兩個(gè)數(shù)組是否擁有一致的元素,例如,以下兩個(gè)數(shù)組由于擁有相同的元素,因此被認(rèn)為是相等的:
- int[] arr1 = new int[]
- {
- 1,2,3,4
- };
- int[] arr2 = new int[]
- {
- 1,2,3,4
- };
在.NET早期版本中,要實(shí)現(xiàn)上述數(shù)組比對功能,必須自己動手編寫一個(gè)函數(shù),在其內(nèi)部使用循環(huán)語句逐個(gè)比較兩個(gè)數(shù)組的對應(yīng)元素,才知道這兩個(gè)數(shù)組是否相等。
在.NET 4.0中,數(shù)組基類Array實(shí)現(xiàn)了一個(gè)新增的接口IStructuralEquatable,從而使得所有數(shù)組都可直接比對其所擁有的元素是否相等。
IStructuralEquatable接口的定義如下,其中最重要的成員就是它所定義的Equals()方法。
- public interface IStructuralEquatable
- {
- bool Equals(object other, IEqualityComparer comparer);
- int GetHashCode(IEqualityComparer comparer);
- }
上述聲明中還涉及另一個(gè)接口IEqualityComparer,它的聲明如下:
- public interface IEqualityComparer
- {
- bool Equals(object x, object y);
- int GetHashCode(object obj);
- }
實(shí)現(xiàn)了IEqualityComparer接口的對象被稱為“集合對象相等比較器”。
.NET 4.0基類庫中提供了好幾個(gè)直接可用的“集合對象相等比較器”,有兩種方式獲取這些預(yù)定義的“集合對象相等比較器”:
(1)使用StructuralComparisons類的靜態(tài)屬性StructuralEqualityComparer獲取一個(gè)StructuralEqualityComparer類型實(shí)例的引用。
延伸閱讀:
“程序集接口最小化”設(shè)計(jì)原則
StructuralComparisons和StructuralEqualityComparer這兩個(gè)類型均屬于System.Collections命名空間,位于.NET的核心程序集mscorlib.dll內(nèi),前者是public的,而后者是internal的。
默認(rèn)情況下,聲明為internal的類型只能在本程序集內(nèi)使用,其它程序集無法“看到”它。
因此,StructuralComparisons類在定義其靜態(tài)屬性StructuralEqualityComparer時(shí),沒有直接向外界暴露StructuralEqualityComparer類型,而是將其轉(zhuǎn)換為公有的IEqualityComparer接口:
- public static class StructuralComparisons
- {
- public static IEqualityComparer StructuralEqualityComparer { get; }
- //……
- }
這種設(shè)計(jì)方法貫徹了.NET組件化開發(fā)中的“程序集接口最小化”原則。該原則說:設(shè)計(jì)一個(gè)程序集時(shí)應(yīng)該盡可能地減少聲明為public的類型。
.NET設(shè)計(jì)者在設(shè)計(jì)public類型StructuralComparisons時(shí),沒有讓其靜態(tài)屬性直接將一個(gè)StructuralEqualityComparer對象的引用返回給外界,而將其轉(zhuǎn)換為一個(gè)外界“知道”的公有接口IEqualityComparer,從而將StructuralEqualityComparer類型的定義完全封裝在程序集內(nèi)部,外界甚至不知道有這么一個(gè)類型的存在。
這種設(shè)計(jì)方式的好處是:
我們可以在程序集內(nèi)部設(shè)計(jì)任意多個(gè)實(shí)現(xiàn)了IEqualityComparer接口的類型,由于這些類型對于外界而言是“透明”的,因此,程序集內(nèi)部的修改對外界程序集使用者可能帶來的影響就很小了。
這種設(shè)計(jì)方法值得注意。
(2)使用EqualityComparer<T>靜態(tài)屬性Default獲取一個(gè).NET4.0針對泛型類型T所提供的默認(rèn)“集合對象相等比較器”對象的引用,同樣地,它沒有將程序集內(nèi)部的某個(gè)具體類型發(fā)布出去,而是玩了一點(diǎn)小花樣,發(fā)布了一個(gè)實(shí)現(xiàn)了IEqualityComparer接口的公有抽象基類EqualityComparer<T>:
- public abstract class EqualityComparer<T> :
- IEqualityComparer, IEqualityComparer<T>
- {
- public static EqualityComparer<T> Default { get; }
- //...
- }
可以將.NET基類庫設(shè)計(jì)者的設(shè)計(jì)思路表述為下圖 。
因此,使用上述兩種方式的任意一種,我們可以寫出以下代碼來直接判斷兩個(gè)整型數(shù)組是否擁有完全一致元素:
- bool IsEqual1=(arr1 as IStructuralEquatable).Equals(
- arr2, StructuralComparisons.StructuralEqualityComparer);
- bool IsEqual2=(arr1 as IStructuralEquatable).Equals(
- arr2, EqualityComparer<int>.Default)
當(dāng)比對兩個(gè)數(shù)組時(shí),如果兩個(gè)數(shù)組的長度不一樣,數(shù)組基類Array所實(shí)現(xiàn)的IStructuralEquatable.Equals()方法將返回false,否則,它逐個(gè)比較兩個(gè)數(shù)組的對應(yīng)元素,找到一個(gè)不同的,返回false,如果一直比較完所有元素,都沒有發(fā)現(xiàn)有不同的,則Equals()方法返回true。
2兩個(gè)數(shù)組“誰大誰小”?
如果兩個(gè)數(shù)組的長度一樣,我們還可以定義這兩個(gè)數(shù)組“誰大誰小”:
- int[] arr1 = new int[]
- {
- 1,2,3,4
- };
- int[] arr2 = new int[]
- {
- 1,2,3,5
- };
上述兩個(gè)數(shù)組中,由于arr1與arr2前幾個(gè)元素都相等,但第4個(gè)元素arr2大于arr1,所以,我們認(rèn)為:arr2“大于”arr1
為了比較兩個(gè)集合的大小,.NET 4.0引入了一個(gè)新的接口IStructuralComparable,并且讓數(shù)組基類Array也實(shí)現(xiàn)了此接口,這意味著在.NET 4.0中,兩個(gè)數(shù)組對象是可以比較“大小”的。
- public interface IStructuralComparable
- {
- int CompareTo(object other, IComparer comparer);
- }
注意上面的接口聲明中用到了一個(gè)實(shí)現(xiàn)IComparer接口的“集合對象大小比較器”對象。.NET基類庫同樣提供了幾個(gè)默認(rèn)的“集合對象大小比較器”可供直接使用,也有兩種方式獲取這些默認(rèn)的“集合對象大小比較器”實(shí)例:
(1)通過我們前面用過的StructuralComparisons類的另一個(gè)靜態(tài)屬性StructuralComparer獲取,它在內(nèi)部使用System.Collections.Comparer類的Default靜態(tài)屬性所引用的包容了本地文化信息(CultureInfo)的Comparer對象來完成比較大小的工作,此對象是CLR在裝入程序集時(shí)創(chuàng)建的。
(2)通過Comparer<T>.Default屬性獲取針對特定類型的默認(rèn)“集合對象大小比較器”對象。
由此,我們可以寫出以下代碼來比較兩個(gè)整型數(shù)組誰大誰?。?/P>
- int result1=(arr1 as IStructuralComparable).CompareTo(
- arr2, StructuralComparisons.StructuralComparer);
- int result2= (arr1 as IStructuralComparable).CompareTo(
- arr2,Comparer<int>.Default)
如果arr1>arr2,我們得到“1”;arr1<arr2,我們得到“-1”;arr1“等于”arr2,我們得到“0”。
3 小結(jié)
由于.NET 4.0數(shù)組基類Array實(shí)現(xiàn)了IStructuralEquatable和IStructuralComparable兩個(gè)接口,從而使得所有數(shù)組都可以直接比較其內(nèi)容了。
#T#
通常情況下,使用.NET 4.0提供的幾個(gè)預(yù)定義集合對象比較器就足夠了,不過,我們也可以通過定義自己的“集合對象相等比較器”(只需定義一個(gè)實(shí)現(xiàn)IEqualityComparer 接口的類)或“集合對象大小比較器”(只需定義一個(gè)實(shí)現(xiàn)IComparer接口的類),從而定義自己的數(shù)組比較規(guī)則。
對于其元素為自定義引用類型的數(shù)組,推薦讓此自定義類型實(shí)現(xiàn)IComparable接口,并且重寫Object.Equals()方法。這么做的目的是讓數(shù)組中的所有對象都可以相互比較,并且能直接調(diào)用數(shù)組基類Array所提供的排序、查找、篩選等功能。
另外,.NET基類庫中相關(guān)的設(shè)計(jì)方案也是值得大家學(xué)習(xí)借鑒的。
我在本文中詳細(xì)介紹了.NET基類庫如何設(shè)計(jì)集合對象相等比較器,但沒有介紹它是如何設(shè)計(jì)集合對象大小比較器的,這個(gè)進(jìn)一步深入探索的任務(wù)就留給好奇心強(qiáng)的讀者,我只想指出一點(diǎn),.NET 基類庫中,集合對象大小比較器與集合對象相等比較器的設(shè)計(jì)思路是類似的。
原文標(biāo)題:.NET 4.0中數(shù)組的新增功能
鏈接:http://www.cnblogs.com/bitfan/archive/2009/12/27/1633625.html