集合就如同數組,被用來存儲和管理一組具有相同性質的對象。除了基本的資料處理功能,集合還提供了各種資料結構及算法的實作,如隊列,連結清單,排序等,可以輕易地完成複雜的資料操作。集合是一個特殊的類,好比容器一樣将一系列相似的項組合在一起,集合中包含的對象稱為集合元素。集合可以分為泛型集合類和非泛型集合類兩種。泛型集合類一般位于System.Collections.Generic命名空間。非泛型集合類位于System.Collections命名空間,除此之外,在System.Collections.Specialized命名空間中也包含了一些有用的集合類。
System.Collections命名空間
System.Conllections是一個命名空間。包括一組接口和可使用的集合類,這些接口和類定義各種對象(如清單,隊列,位數組,哈希表和字典等)的集合。
該命名空間下常用的.NET非泛型集合類如表所示:
類 | 說明 |
ArrayList | 數組集合類,使用大小可按需要動态增加的數組實作IList接口 |
BitArray | 布爾集合類,管理位值的壓縮數組,該值表示布爾值,其中true表示位是打開的(1),false表示位是閉合的(0) |
Hashtable | 哈希表,表示鍵/值對的集合,這些鍵/值對根據鍵的哈希代碼進行組織 |
Queue | 隊列,表示對象的先進先出集合 |
SortedList | 排序集合類,表示鍵/值對的集合,這些鍵/值對按鍵排序并可按照鍵和索引通路。 |
Stack | 堆棧,表示對象的簡單後進先出非泛型集合 |
該命名空間下常用的.NET非泛型集合類的接口如下:
接口 | |
ICollection | 定義所有非泛型集合的大小,枚舉數和同步方法 |
IComparer | 公開一種比較兩個對象的方法。 |
IDictionary | 表示鍵/值對的非通用集合 |
IDictionaryEnumerator | 枚舉非泛型字典的元素 |
IEnumerator | 支援對非泛型集合的簡單疊代 |
IList | 表示可按照索引單獨通路的對象的非泛型集合 |
動态數組ArrayList類
可以将ArrayList類了解為數組類Array的優化版本,該類既有數組的特征,又有集合的特性。
ArrayList是System.Collections命名空間中的類,類似于數組,有人稱其為動态數組,其容量可以根據需要自動擴充,元素的索引也可以根據元素數量重新配置設定,可以動态實作元素的添加,删除等操作。可以将ArrayList類了解為Array的優化版本,該類既有數組的特征,又有集合的特性。
例如,既可以通過下标進行元素通路,對元素排序,搜尋,又可以像處理集合一樣添加,在指定索引處插入及删除元素。
ArrayList類的幾個常用屬性
屬性名稱 | 屬性說明 |
Capacity | 擷取或設定ArrayList可包含的元素數,預設為4 |
Count | 擷取ArrayList中實際包含的元素數 |
Item | 擷取或設定指定索引處的元素 |
ArrayList類常用的方法
方法名稱 | 方法說明 |
Add | 将元素添加到ArrayList的結尾處 |
AddRange | 在ArrayList的末尾增加一定範圍内的元素 |
Clear | 清除ArrayList中所有元素 |
Contains | 檢查某元素是否在ArrayList中 |
IndexOf | 傳回ArrayList中某個元素值得第一個比對項對應的索引 |
Insert | 将元素插入ArrayList的指定索引處 |
Remove | 從ArrayList中移除特定元素的第一個比對項 |
Reverse | 将ArrayList或它的一部分中元素的順序反轉 |
Sort | 對ArrayList或它的一部分中元素進行排序 |
由于ArrayList中元素的類型預設為object,是以在擷取集合元素時需要強制進行轉換。并且由于object是引用類型,在與值類型進行轉換時會引起裝箱和拆箱的操作,是以會付出性能的一些代價。
ArrayList類的使用
建立ArrayList
可以使用3種重載構造函數的一種,還可以使用ArrayList的靜态方法Repeat建立一個新的ArrayList。這3個構造的聲明如下
使用預設的初始化容量建立ArrayList,該執行個體沒有任何元素。格式如下:
public ArrayList();
使用實作了ICollection接口的集合類來初始化新建立的ArrayList。格式如下:
public ArrayList(ICollection C);
指定一個整數值來初始化ArrayList的容量,建立ArrayList,格式如下:
public ArrayList(int capacity)
例如:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
ArrayList al1 = new ArrayList();
al1.Add("Hello");
al1.Add("C#");
al1.Add("World!");
Console.WriteLine("該ArrayList的容量是:{0},元素的個數是:{1}",al1.Capacity,al1.Count);
ArrayList al2 = new ArrayList(al1);
ArrayList al3 = new ArrayList(18);
Console.WriteLine("該ArrayList的容量是:{0},元素的個數是{1}",al3.Capacity,al3.Count);
ArrayList al4 = ArrayList.Repeat("張三", 3);
for (int a = 0; a < al4.Count; a++)
{
Console.WriteLine(al4[a]);
}
Console.ReadKey();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
ArrayList al1 = new ArrayList();
al1.Add("Hello");
al1.Add("C#");
al1.Add("World!");
Console.WriteLine("該ArrayList的容量是:{0},元素的個數是:{1}",al1.Capacity,al1.Count);
ArrayList al2 = new ArrayList(al1);
ArrayList al3 = new ArrayList(18);
Console.WriteLine("該ArrayList的容量是:{0},元素的個數是{1}",al3.Capacity,al3.Count);
ArrayList al4 = ArrayList.Repeat("張三", 3);
for (int a = 0; a < al4.Count; a++)
{
Console.WriteLine(al4[a]);
}
Console.ReadKey();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
ArrayList al1 = new ArrayList();
al1.Add("Hello");
al1.Add("C#");
al1.Add("World!");
Console.WriteLine("該ArrayList的容量是:{0},元素的個數是:{1}",al1.Capacity,al1.Count);
ArrayList al2 = new ArrayList(al1);
ArrayList al3 = new ArrayList(18);
Console.WriteLine("該ArrayList的容量是:{0},元素的個數是{1}",al3.Capacity,al3.Count);
ArrayList al4 = ArrayList.Repeat("張三", 3);
for (int a = 0; a < al4.Count; a++)
{
Console.WriteLine(al4[a]);
}
Console.ReadKey();
}
}
}
運作結果:
向ArrayList中添加元素的方法
1.Add方法将單個元素添加到清單的尾部;AddRange方法擷取一個實作ICollection接口的集合執行個體,例如Array,Queue,Stack等,并将這個集合執行個體按順序添加到清單的尾部。
2.也可以使用Insert和InsertRange方法向ArrayList中指定位置插入元素;Insert方法添加單個元素到指定位置,InsertRange從指定的位置開始添加一個實作了ICollection接口的執行個體。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
ArrayList al1 = new ArrayList(20);
al1.Add("我是元素1");
al1.Add("我是元素2");
al1.Add("我是元素3");
string[] str = { "我是元素4","我是元素5","我是元素6"};
al1.AddRange(str);
al1.Insert(0, "新增的第一個元素");
ArrayList al2 = new ArrayList();
al2.Add("我是al2新增的第一個元素");
al2.Add("我是al2新增的第二個元素");
al1.InsertRange(2,al2);
Console.WriteLine("該ArrayList的容量是:{0},元素的個數是:{1}",al1.Capacity,al1.Count);
for (int a = 0; a < al1.Count; a++)
{
Console.WriteLine(al1[a]);
}
Console.ReadKey();
}
}
}
運作結果
删除ArrayList中的元素
ArrayList提供了三種方法可以将指定元素從集合中删除,這三種方法是Remove,RemoveAt和RemoveRange
1.Remove方法接受一個object類型的參數,用于移除指定元素值得第一個比對集合元素。
2.RemoveAt方法接受一個int類型的參數,用于删除指定索引的集合元素。
3.RemoveRange方法從集合中移除一定範圍的元素。
還可以使用Clear方法從ArrayList中移除所有的元素。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
ArrayList al1 = new ArrayList(20);
al1.AddRange(new string[6] { "元素1", "元素2", "元素3", "元素4", "元素5", "元素6" });
Console.WriteLine("該ArrayList的容量是:{0},元素的個數是:{1}",al1.Capacity,al1.Count);
al1.Remove("元素2");
al1.RemoveAt(2);
al1.RemoveRange(0,2);
for (int a = 0; a < al1.Count; a++)
{
Console.WriteLine(al1[a]);
}
al1.Clear();
Console.ReadKey();
}
}
}
運作結果為:
排序
可以使用Sort方法對ArrayList集合中的元素進行排序。Sort有3種重載方法。
使用集合元素的比較方式進行排序:
public virtual void Sort();
使用自定義比較器進行排序:
public virtual void Sort(IComparer comparer);
使用自定義比較器進行指定範圍的排序:
public virtual void Sort(int index,int count,IComparer comparer);
例如使用集合元素的比較方式進行排序的代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
ArrayList al1 = new ArrayList();
al1.AddRange(new string[8] { "Array1", "Array3", "Array6", "Array5", "Array8","Array2","Array7","Array4" });
al1.Sort();
Console.WriteLine("該ArrayList的容量是:{0},元素的個數是:{1}",al1.Capacity,al1.Count);
for (int a = 0; a < al1.Count; a++)
{
Console.WriteLine(al1[a]);
}
al1.Clear();
Console.ReadKey();
}
}
}
至于自定義的排序,在後面會提到。
查找ArrayList中的集合元素
在數組清單中查找元素,最常使用的是IndexOf或LastIndexOf方法,另外,還可以使用BinarySearch方法進行搜尋。IndexOf方法從前向後搜指定的字元串,如果找到,就傳回比對的第一項的自0開始的索引,否則傳回-1,LastIndexOf方法是從後向前搜尋指定字元串,如果找到,則傳回比對的最後一項的自0開始的索引,否則傳回-1。這兩個方法各自有三個重載版本。表示從指定的索引處開始搜尋或者是從指定索引處搜尋指定長度的字元串。BinarySearch使用二分算法從集合中搜尋指定的值,并傳回找到的從0開始的索引,否則傳回-1。
執行個體代碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string[] str= { "Array1", "Array2", "Array3", "Array4", "Array5","Array6"};
ArrayList al1 = new ArrayList(str);
int i = al1.IndexOf("Array3");
Console.WriteLine("Array3元素在集合中的位置是"+i);
i = al1.LastIndexOf("Array5");
Console.WriteLine("Array5元素在集合中的位置是" + i);
int j = al1.BinarySearch("Array3");
if (j > 0)
{
Console.WriteLine("Array3元素在集合中的位置是" + j);
}
else
{
Console.WriteLine("沒有找到Array3元素" );
}
Console.ReadKey();
}
}
}
ArrayList的周遊
ArrayList内部維護着一個數組,可以通過下标進行通路,而且ArrayList實作了IEnumerable接口,是以要周遊集合,可以使用for和foreach方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
ArrayList al1 = new ArrayList(new string[5]{"元素1","元素2","元素3","元素4","元素5"});
for (int i = 0; i <al1.Count; i++)
{
Console.Write(al1[i]);
}
foreach (object s in al1)
{
Console.Write(s);
}
Console.ReadKey();
}
}
}
例如用ArrayList編寫一個管理客戶的程式:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication2
{
class CustomerInfo
{
private static ArrayList CustomerList = new ArrayList();
private String id;
private String name;
private String address;
public CustomerInfo() { }
public CustomerInfo(String myid, String myname, String myaddress)
{
id = myid;
name = myname;
address = myaddress;
}
public String ID
{
set
{
id = value;
}
get
{
return id;
}
}
public String Name
{
get
{
return name;
}
set
{
name = value;
}
}
public String Address
{
get
{
return address;
}
set
{
address = value;
}
}
public static void AddCustomer(CustomerInfo aCustomerInfo)
{
CustomerList.Add(aCustomerInfo);
}
public static void Delete(CustomerInfo oo)
{
int i=CustomerList.IndexOf(oo);
if (i < 0)
{
Console.WriteLine("所要删除對象不存在");
}
else
{
CustomerList.RemoveAt(i);
}
}
public static void Show()
{
foreach (CustomerInfo s in CustomerList)
{
Console.WriteLine(s.ID+", "+s.Name+", "+s.Address);
}
}
public static void SortByName()
{
CustomerList.Sort(new CustomerNameCompare());
}
}
public class CustomerNameCompare : IComparer
{
public int Compare(object x, object y)
{
return new CaseInsensitiveComparer().Compare(((CustomerInfo)y).Name, ((CustomerInfo)x).Name);
}
}
class Program
{
static void Main(string[] args)
{
CustomerInfo a1 = new CustomerInfo("ID110","李四","河南鄭州市");
CustomerInfo.AddCustomer(a1);
CustomerInfo a2 = new CustomerInfo("ID2050","王五","湖南長沙");
CustomerInfo.AddCustomer(a2);
CustomerInfo a3 = new CustomerInfo("ID2035","趙三","河南鄭州市");
CustomerInfo.AddCustomer(a3);
Console.WriteLine("排序前的集合排列");
CustomerInfo.Show();
CustomerInfo.SortByName();
Console.WriteLine("排序後的集合排列");
CustomerInfo.Show();
CustomerInfo a4 = new CustomerInfo("ID0031","趙七","河北石家莊市");
CustomerInfo.AddCustomer(a4);
Console.WriteLine("添加一個客戶後的所有資訊");
CustomerInfo.Show();
CustomerInfo.Delete(a4);
Console.WriteLine("删除一個客戶對象後的資訊");
CustomerInfo.Show();
Console.ReadKey();
}
}
}
還可以在CustomerInfo中添加DeleteByName方法,實作按照姓名删除客戶對象
public static void DeleteByName(string name)
{
for (int i = 0; i < CustomerList.Count; i++)
{
CustomerInfo aa = (CustomerInfo)CustomerList[i];
if (aa.Name == name)
{
CustomerList.RemoveAt(i);
break;
}
}
}
在類CustomerInfo類中添加SortByID方法,實作用ID實作排序。
public static void SortByID()
{
CustomerList.Sort(new CustomerIDCompare());
}
添加CustomerIDCompare如下面代碼:
public class CustomerIDCompare : IComparer
{
public int Compare(object x, object y)
{
return new CaseInsensitiveComparer().Compare(((CustomerInfo)x).ID, ((CustomerInfo)y).ID);
}
}
main方法代碼如下:
CustomerInfo a1 = new CustomerInfo("ID110","李四","河南鄭州市");
CustomerInfo.AddCustomer(a1);
CustomerInfo a2 = new CustomerInfo("ID2050","王五","湖南長沙");
CustomerInfo.AddCustomer(a2);
CustomerInfo a3 = new CustomerInfo("ID2035","趙三","河南鄭州市");
CustomerInfo.AddCustomer(a3);
Console.WriteLine("排序前的集合排列");
CustomerInfo.Show();
CustomerInfo.SortByID();
Console.WriteLine("排序後的集合排列");
CustomerInfo.Show();
CustomerInfo a4 = new CustomerInfo("ID0031","趙七","河北石家莊市");
CustomerInfo.AddCustomer(a4);
Console.WriteLine("添加一個客戶後的所有資訊");
CustomerInfo.Show();
CustomerInfo.DeleteByName("趙三");
Console.WriteLine("删除一個客戶對象後的資訊");
CustomerInfo.Show();
Console.ReadKey();
HashTable類
HashTable稱為哈希表,和ArrayList不同的是它利用鍵/值來存儲資料。在哈希表中,每一個元素都是一個鍵/值對,并且是一一對應的,通過“鍵”就可以得到“值”。如果存儲電話号碼,通常是将姓名和号碼存在一起。存儲時把姓名當作鍵,号碼當作值,通過姓名即可查到電話号碼,這就是一個典型的哈希表存儲方式。HashTable是System.Collections命名空間中的一個重要的類,如果把哈希表當作字典,那麼“鍵”就是字典中查的單詞,“值”就是關于單詞的解釋内容。正因為有這個特點,是以有人把哈希表稱做“字典”。
在HashTable内部維護着一個哈希表。内部哈希表為插入到其中的每個鍵進行哈希編碼,在後續的檢索操作中,通過哈希編碼就可以周遊所有元素,這種方法為檢索操作提供了較佳的性能。在.NET中鍵和值可以是任何一種對象,例如字元串,自定義類等。在背景,當插入鍵值對到HashTable中時,HashTable使用每個鍵所引用對象的GetHashCode()方法擷取一個哈西編碼,存入到HashTable中。哈希表常用的屬性和方法如表所示:
擷取包含在Hashtable中的鍵/值對的數目 | |
Keys | 擷取包含在HashTable中的所有鍵的集合 |
Values | 擷取包含在HashTable中的所有值得集合 |
将帶有指定鍵和值的元素添加到HashTable中 | |
從HashTable中移除所有元素 | |
确定HashTable是否包含特定鍵 | |
GetEnumerator | 傳回IDictionaryEnumerator,可以周遊HashTable |
從HashTable中移除帶有指定鍵的元素。 |
HashTable類提供了15個重載的和構造函數,常用的4個HashTable構造函數聲明如下:
1.使用預設的初始容量,加載因子,哈希代碼,提供程式和比較器來初始化HashTable類的執行個體。
public HashTable();
2.使用指定容量,預設加載因子,預設哈希代碼提供程式和比較器來初始化HashTable類的執行個體。
public HashTable(int Capacity);
3.使用指定的容量,加載因子來初始化HashTable類的執行個體。
public HashTable(int capacity,float loadFactor);
4.通過将指定字典中的元素複制到新的HashTable對象中,初始化HashTable類的一個新執行個體。新HashTable對象的初始化容量等于複制的元素數,并且使用預設的加載因子,哈希代碼提供程式和比較器。
public HashTable(IDictionary d);
下面的例子示範如何使用4種方法建構哈希表
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Hashtable h1 = new Hashtable();
Hashtable h2 = new Hashtable(20);//指定初始容量
Hashtable h3 = new Hashtable(20, 0.8f);//指定初始容量,和加載因子
Hashtable h4 = new Hashtable(h3);
Console.ReadKey();
}
}
}
使用HashTable提供的屬性和方法來操作哈希表。例如:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Hashtable h1 = new Hashtable();
h1.Add("txt","notepad.exe");
h1.Add("bmp","paint.exe");
h1.Add("dib","paint.exe");
h1.Add("rtf","wordpad.exe");
Console.WriteLine("鍵=\"rtf\",值={0}",h1["rtf"]);
h1["rtf"] = "winword.exe";
Console.WriteLine("鍵=\"rtf\",值={0}", h1["rtf"]);
h1["doc"] = "winword.exe";
if (!h1.ContainsKey("ht"))
{
h1.Add("ht","hypertrm.exe");
Console.WriteLine("為鍵ht添加值:{0}",h1["ht"]);
}
Console.WriteLine("周遊哈希表:");
foreach (DictionaryEntry de in h1)
{
Console.WriteLine("鍵={0},值={1}",de.Key,de.Value);
}
Console.WriteLine("\n删除(\"doc\")");
h1.Remove("doc");
if (!h1.ContainsKey("doc"))
{
Console.WriteLine("鍵\"doc\"沒有找到");
}
Hashtable h2 = new Hashtable(20);//指定初始容量
Hashtable h3 = new Hashtable(20, 0.8f);//指定初始容量,和加載因子
Hashtable h4 = new Hashtable(h3);
Console.ReadKey();
}
}
}
通過鍵集和值集周遊哈希表中的鍵或值的方法舉例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Hashtable h1 = new Hashtable();
h1.Add("txt","notepad.exe");
h1.Add("bmp","paint.exe");
h1.Add("dib","paint.exe");
h1.Add("rtf","wordpad.exe");
ICollection valueColl = h1.Values;
foreach (string s in valueColl)
{
Console.WriteLine("值={0}",s);
}
ICollection keyColl = h1.Keys;
foreach (string s in keyColl)
{
Console.WriteLine("鍵={0}",s);
}
Console.ReadKey();
}
}
}
通用類型————泛型。
.NET提供有功能強大的泛型特性,利用泛型,可以減少代碼編寫的工作量,提高程式的運作效率。
泛型?什麼是泛型,泛型是一種類型占位符,或稱之為類型參數。我們知道在一個方法中,一個變量的值可以作為參數,但其實這個變量的本身也可以作為參數,泛型允許我們在調用的時候再指定這個參數是什麼類型。泛型就好比Word中的模闆,在Word的模闆中提供基本的文檔編輯内容,在定義Word模闆時,對具體編輯哪種類型的文檔是未知的。在.NET中泛型則提供了類,結構,接口和方法的模闆,與定義Word模闆時類似,定義泛型時的具體類型是未知的。在.NET中。泛型能夠給我們帶來的好處是“類型安全和減少裝箱,拆箱”。
例如在ArrayList類中,所有元素類型都為object類型。.NET中的object類是所有類的基類,是以ArrayList類能夠接受任何類型的值作為它的元素。當使用ArrayList中的元素時,必須要強制進行類型的轉換将元素轉換為合适的元素類型。如果元素是值類型的值時,會引起CLR進行拆箱和裝箱的操作,造成一定的性能開銷,而且,還需要小心處理類型轉換中可能出現的錯誤,但是很多時候我們會把ArrayList集合中的元素定義為确定的類型,或稱之為強類型,這樣就可以減少性能的開銷,而且也避免類型轉換中的‘可能會出現的錯誤,但是如果還需要強類型字元串值,布爾值或其他的類型時,就必須一一地實作這些強類型類,這些重複的工作就會增加代碼量,為此我們引入了泛型來處理這種不足,經由指定一個或多個類型占位符,在處理類型操作時,不需要知道集體的類型,而将确定具體類型的工作放在運作時實作。
使用泛型
泛型可以定義泛型類,泛型方法,泛型接口等。在System.Collections.Generic命名空間中包含有幾個泛型集合類,List<T>和Dictionary<K,V>是其中非常重要的兩種,泛型接口IComparable<T>,ICompaer<T>在實際中也有很重要的作用。
1.泛型集合List<T>和泛型接口ICompaer<T>,IComparable<T>
泛型最重要的應用就是集合操作,使用泛型集合可以提高代碼重用性類型安全,并擁有佳的性能。List<T>的用法和ArrayList相似,但是有更好的安全性,無需裝箱,拆箱
定義一個List<T>泛型集合的文法如下:
List<T> 集合名=new List<T>();
在泛型的定義中,泛型類型參數"<T>"是必須指定的,其中T是定義泛型類時的占位符,其并不是一種類型,僅代表某種可能的類型。在定義時T會被使用的類型替代,泛型集合List<T>中隻能有一個參數類型,"<T>"中的T可以對集合中的元素類型進行限制。
注意:泛型集合必須執行個體化,執行個體化時和普通類執行個體化相同,必須在後面加上“()”;
List<T>的添加,删除和檢索等方法和ArrayList相似,但是不需要像ArrayList那樣裝箱和拆箱。
如:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
List<string> Is = new List<string>();
Is.Add("泛型集合元素1");
Is.Add("泛型集合元素2");
Is.Add("泛型集合元素3");
Console.ReadKey();
}
}
}
泛型接口IComparer<T>,定義了為比較兩個對象而實作的方法。定義如下:
public interface IComparer<T>
{
int Compare(T x, T y);
}
類型參數“T”是要比較的對象的類型。Compare方法比較兩個對象并傳回一個值,訓示一個對象是小于,等于還是大于另一個對象。參數x是要比較的第一個對象,y是要比較的第二個對象,均屬于T類型,如果傳回值大于0,則x>y;如果傳回值小于0,則x<y;如果傳回值等于0,則x=y。
IComparer<T>泛型接口主要作用是:作為參數傳入Sort()方法,實作對象比較方式的排序。
Sort方法的文法如下:
#region 程式集 mscorlib.dll, v4.0.30319
// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Profile\Client\mscorlib.dll
#endregion
using System;
namespace System.Collections.Generic
{
// 摘要:
// 定義類型為比較兩個對象而實作的方法。
//
// 類型參數:
// T:
// 要比較的對象的類型。
public interface IComparer<in T>
{
// 摘要:
// 比較兩個對象并傳回一個值,訓示一個對象是小于、等于還是大于另一個對象。
//
// 參數:
// x:
// 要比較的第一個對象。
//
// y:
// 要比較的第二個對象。
//
// 傳回結果:
// 一個帶符号整數,它訓示 x 與 y 的相對值,如下表所示。值含義小于零x 小于 y。零x 等于 y。大于零x 大于 y。
int Compare(T x, T y);
}
}
public void Sort(IComparer<T> compaer)
使用IComparer<T>接口實作按照客戶的姓名進行排序的方法例如:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication2
{
class CustomerInfo
{
private static List<CustomerInfo> CustomerList = new List<CustomerInfo>();
private String id;
private String name;
private String address;
public CustomerInfo() { }
public CustomerInfo(String myid, String myname, String myaddress)
{
id = myid;
name = myname;
address = myaddress;
}
public String ID
{
set
{
id = value;
}
get
{
return id;
}
}
public String Name
{
get
{
return name;
}
set
{
name = value;
}
}
public String Address
{
get
{
return address;
}
set
{
address = value;
}
}
public static void AddCustomer(CustomerInfo aCustomerInfo)
{
CustomerList.Add(aCustomerInfo);
}
public static void Delete(CustomerInfo oo)
{
int i = CustomerList.IndexOf(oo);
if (i < 0)
{
Console.WriteLine("所要删除對象不存在");
}
else
{
CustomerList.RemoveAt(i);
}
}
public static void Show()
{
foreach (CustomerInfo s in CustomerList)
{
Console.WriteLine(s.ID + ", " + s.Name + ", " + s.Address);
}
}
public static void SortByName()
{
CustomerList.Sort(new CustomerNameCompare());
}
}
public class CustomerNameCompare : IComparer<CustomerInfo>
{
public int Compare(CustomerInfo x, CustomerInfo y)
{
return (x.Name.CompareTo(y.Name));
}
}
class Program
{
static void Main(string[] args)
{
CustomerInfo a1 = new CustomerInfo("ID110", "李四", "河南鄭州市");
CustomerInfo.AddCustomer(a1);
CustomerInfo a2 = new CustomerInfo("ID2050", "王五", "湖南長沙");
CustomerInfo.AddCustomer(a2);
CustomerInfo a3 = new CustomerInfo("ID2035", "趙三", "河南鄭州市");
CustomerInfo.AddCustomer(a3);
Console.WriteLine("排序前的集合排列");
CustomerInfo.Show();
CustomerInfo.SortByName();
Console.WriteLine("排序後的集合排列");
CustomerInfo.Show();
CustomerInfo a4 = new CustomerInfo("ID0031", "趙七", "河北石家莊市");
CustomerInfo.AddCustomer(a4);
Console.WriteLine("添加一個客戶後的所有資訊");
CustomerInfo.Show();
CustomerInfo.Delete(a4);
Console.WriteLine("删除一個客戶對象後的資訊");
CustomerInfo.Show();
Console.ReadKey();
}
}
}
使用IComparable<T>實作比較對象大小的功能。
IComparable<T>是常用的泛型接口。泛型接口也具有一般接口的共同特點,即在接口中可以包含字段,屬性,方法和索引器,但都不能夠實作。泛型接口IComparable<T>的功能和接口IComparable相似,規定了一個沒有實作的方法Compare(Object obj)文法如下:
#region 程式集 mscorlib.dll, v4.0.30319
// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Profile\Client\mscorlib.dll
#endregion
using System.Runtime.InteropServices;
namespace System
{
// 摘要:
// 定義一種特定于類型的通用比較方法,值類型或類通過實作此方法對其執行個體進行排序。
[ComVisible(true)]
public interface IComparable
{
// 摘要:
// 将目前執行個體與同一類型的另一個對象進行比較,并傳回一個整數,該整數訓示目前執行個體在排序順序中的位置是位于另一個對象之前、之後還是與其位置相同。
//
// 參數:
// obj:
// 與此執行個體進行比較的對象。
//
// 傳回結果:
// 一個值,訓示要比較的對象的相對順序。傳回值的含義如下:值含義小于零此執行個體小于 obj。零此執行個體等于 obj。大于零此執行個體大于 obj。
//
// 異常:
// System.ArgumentException:
// obj 不具有與此執行個體相同的類型。
int CompareTo(object obj);
}
}
此接口中的CompareTo用于比較對象的大小。如果一個類實作了該接口中的這個方法,說明這個類的對象是可以比較大小的。如果目前對象小于obj,傳回值小于0;如果目前對象大于obj,傳回值大于0;如果目前對象等于obj傳回值等于0。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace ConsoleApplication2
{
class CustomerInfo : IComparable<CustomerInfo>
{
private String id;
private String name;
private String address;
public CustomerInfo() { }
public CustomerInfo(String myid, String myname, String myaddress)
{
id = myid;
name = myname;
address = myaddress;
}
public String ID
{
get
{
return id;
}
set
{
id = value;
}
}
public String Name
{
get
{
return name;
}
set
{
name = value;
}
}
public String Address
{
get
{
return address;
}
set
{
address = value;
}
}
public int CompareTo(CustomerInfo objss)
{
return this.Name.CompareTo(objss.Name);
}
}
class Program
{
static void Main(string[] args)
{
CustomerInfo a1 = new CustomerInfo("id0001","李四","河南鄭州市");
CustomerInfo a2 = new CustomerInfo("id0002","王五","湖南長沙市");
if (a1.CompareTo(a2) > 0)
{
Console.WriteLine("{0}的姓名比{1}的姓名靠前", a1.Name, a2.Name);
}
else
{
Console.WriteLine("{0}的姓名比{1}的姓名靠後", a1.Name, a2.Name);
}
Console.ReadKey();
}
}
}
提示:在Compare方法中降序排序使用y.CompareTo(x)寫法,升序排序使用x.CompareTo(y)寫法實作。
泛型集合Dictionary<K,V>
在System.Collections.Generic命名空間,與HashTable相對應的泛型集合是Dictionary<K,V>,其存儲資料的方式和哈希表相似,通過鍵/值來儲存元素,并具有泛型的全部特征,編譯時檢查類型限制,讀取時無需進行類型轉換。定義Dictionary<K,V>泛型集合中的方法如下:
Dictionary<k,V>泛型集合名=new Dictionary<K,v>();
其中K為占位符,具體的定義時用存儲鍵“Key”的資料類型代替,“V”同樣也是占位符,用元素的值“value”的資料類型代替,這樣就在定義該集合時,聲明了存儲元素的鍵和值的資料類型,保證了類型的安全。
Dictionary<string, string> op = new Dictionary<string, string>();
Dictionary<string, int> op1 = new Dictionary<string, int>();
在這個Dictionary<K,V>的生命中,"<string,string>(<string,int>)"中的第一個string表示集合中Key的類型,第二個string表示Value的類型。
Dictionary<string, string> op = new Dictionary<string, string>();
Dictionary<string, int> op1 = new Dictionary<string, int>();
op.Add("txt","notepad.exe");
op.Add("bmp","paint.exe");
op1.Add("naem", 12);
op1.Add("age",20);
使用泛型的好處:
1.性能高。使用泛型不需要進行類型轉換,可以避免裝箱和拆箱,能提高性能。
2.類型安全。泛型集合對其存儲對象進行了類型的限制,不是定義時聲明的類型,是無法存儲到泛型集合中的,進而保證了資料的類型安全。
3.代碼重用。使用泛型可以最大限度地重用代碼,保護類型的安全以及提高性能。
在處理集合類時,如果你遇到下列情況,可以考慮使用泛型:
1.如需要對多種類型進行相同的操作處理。
2.如需要處理值類型,使用泛型則可以避免裝箱和拆箱帶來的性能開銷。
3.使用泛型可以在應用程式編譯時發現類型錯誤,增強程式的健壯性。
4.減少不必要的重複編碼,是代碼結構更加清晰。