前篇【C# 3.0 集合運算 (交集、差集、聯集、互斥) - Value Type】介紹實值型別的集合運算,本篇介紹參考型別 (reference type) 的集合運算。首先,繼續拿我常用的 Product 類別,首先建立兩個 List<Product> 集合,當作練習之用。 範例碼,如下: 1: var pList1 = new List<Product> 2: { 3: new Product {ID = 1, Name = "A", Price = 7, ShipDate = new DateTime(2006, 1, 19)}, 4: new Product {ID = 2, Name = "B", Price = 237, ShipDate = new DateTime(2006, 10, 17)}, 5: new Product {ID = 3, Name = "C", Price = 17, ShipDate = new DateTime(2007, 2, 12)}, 6: new Product {ID = 4, Name = "D", Price = 57, ShipDate = new DateTime(2005, 9, 11)} 7: }; 8: 9: var pList2 = new List<Product> 10: { 11: new Product {ID = 1, Name = "A", Price = 7, ShipDate = new DateTime(2006, 1, 19)}, 12: new Product {ID = 5, Name = "E", Price = 88, ShipDate = new DateTime(2008, 12, 10)}, 13: new Product {ID = 6, Name = "F", Price = 99, ShipDate = new DateTime(2008, 6, 4)}, 14: new Product {ID = 4, Name = "D", Price = 57, ShipDate = new DateTime(2005, 9, 11)} 15: }; 16: 17: // pList1 聯集 pList2 18: foreach (var product in pList1.Union(pList2)) 19: { 20: Console.WriteLine(product.ToString()); 21: } 輸出的結果為: 1: ID: 1, Name: A, Price: 7, ShipDate: 2006/1/19 2: ID: 2, Name: B, Price: 237, ShipDate: 2006/10/17 3: ID: 3, Name: C, Price: 17, ShipDate: 2007/2/12 4: ID: 4, Name: D, Price: 57, ShipDate: 2005/9/11 5: ID: 1, Name: A, Price: 7, ShipDate: 2006/1/19 6: ID: 5, Name: E, Price: 88, ShipDate: 2008/12/10 7: ID: 6, Name: F, Price: 99, ShipDate: 2008/6/4 8: ID: 4, Name: D, Price: 57, ShipDate: 2005/9/11 這結果似乎有點不太對勁,沒有如我們所預期合併為 Product ID { 1 2 3 4 5 6 } 的集合,而是列出 Product ID { 1 2 3 4 1 5 6 4 } 的組合。這是因為我們缺少了一個動作就是覆寫自訂類別的 Equals() 方法、GetHashCode()方法,使得無法讓編譯器知道什麼是相同的物件。所以我們下一步就是在自定類別 Product 中撰寫 Equals() 方法、GetHashCode()方法。 範例碼,如下: 1: public class Product 2: { 3: public int ID { get; set; } 4: public string Name { get; set; } 5: public double Price { get; set; } 6: public DateTime ShipDate { get; set; } 7: 8: public override string ToString() 9: { 10: return string.Format("ID: {0}, Name: {1}, Price: {2}, ShipDate: {3}", ID, Name, Price, ShipDate.ToShortDateString()); 11: } 12: 13: public override bool Equals(object obj) 14: { 15: if(obj is Product) 16: { 17: Product p = (Product) obj; 18: return (p.ID == ID && p.Name == Name && p.Price == Price && p.ShipDate == ShipDate); 19: } 20: return false; 21: } 22: 23: public override int GetHashCode() 24: { 25: return ToString().GetHashCode(); 26: } 27: } 此時,我們再一次執行剛剛的程式碼,結果就會變成以下的結果: 1: // pList1 聯集 pList2 2: foreach (var product in pList1.Union(pList2)) 3: { 4: Console.WriteLine(product.ToString()); 5: } 6: 7: // pList1 聯集 pList2 輸出結果 8: ID: 1, Name: A, Price: 7, ShipDate: 2006/1/19 9: ID: 2, Name: B, Price: 237, ShipDate: 2006/10/17 10: ID: 3, Name: C, Price: 17, ShipDate: 2007/2/12 11: ID: 4, Name: D, Price: 57, ShipDate: 2005/9/11 12: ID: 5, Name: E, Price: 88, ShipDate: 2008/12/10 13: ID: 6, Name: F, Price: 99, ShipDate: 2008/6/4 撰寫了 Equals() 方法、GetHashCode()方法後,剩下來的交集、差集、互斥等集合運算就跟實值型別 (value type) 的使用方式,沒有啥兩樣囉,範例碼如下: 1: // pList1 交集 pList2 2: foreach (var product in pList1.Intersect(pList2)) 3: { 4: Console.WriteLine(product.ToString()); 5: } 6: 7: // pList1 交集 pList2 輸出結果 8: // ID: 1, Name: A, Price: 7, ShipDate: 2006/1/19 9: // ID: 4, Name: D, Price: 57, ShipDate: 2005/9/11 10: 11: // pList1 差集 pList2 12: foreach (var product in pList1.Except(pList2)) 13: { 14: Console.WriteLine(product.ToString()); 15: } 16: 17: // pList1 差集 pList2 輸出結果 18: // ID: 2, Name: B, Price: 237, ShipDate: 2006/10/17 19: // ID: 3, Name: C, Price: 17, ShipDate: 2007/2/12 20: 21: // pList1 互斥 pList2 22: foreach (var product in pList1.Except(pList2).Union(pList2.Except(pList1))) 23: { 24: Console.WriteLine(product.ToString()); 25: } 26: 27: // pList1 互斥 pList2 輸出結果 28: // ID: 2, Name: B, Price: 237, ShipDate: 2006/10/17 29: // ID: 3, Name: C, Price: 17, ShipDate: 2007/2/12 30: // ID: 5, Name: E, Price: 88, ShipDate: 2008/12/10 31: // ID: 6, Name: F, Price: 99, ShipDate: 2008/6/4
|
|