Abstract
在OO設計中,對應於Relational Database的一筆資料,我們會用一個object,如Customer,但多筆資料呢?有些人會用DataSet,有些人會用List<Customer>,這些方法都不錯,但若要設計自己的Collection:Customers type,那該怎麼做呢?
Introduction
使用DataSet(DataTable,DataReader....)或List<Customer>這些代表Collection,理論上並沒有什麼錯,事實上很多人也都這樣用,缺點就是比較沒有OO的flavor。理想上,既然有Customer class代表一筆資料,就應該有Customers class代表多筆資料,而N-Tiers間的傳輸應該是Customers collection,而非DataSet或List<Customer>。
要產生自己的Collection,有兩種方式,一個是.NET 1.0的方式,一個是.NET 2.0的方式。
.NET 1.0方式(在.NET 2.0仍然可以使用)
繼承CollectionBase,CollectionBase是一個abstract class,implement了IList ,ICollection,IEnumerable,已經為Collection做好了基礎架構,我們要做的就是overload this[]、IndexOf()、Add()、Remove()就好,其他的事情,CollectionBase已經幫我們做好了。


1/**//**//**//*
2(C) OOMusou 2007 http://oomusou.cnblogs.com
3
4Filename : BuildOwnCollection1.cs
5Compiler : Visual Studio 2005 / C# 2.0
6Description : Demo how to build strong typed collection
7Release : 06/19/2007 1.0
8*/
9using System;
10using System.Collections;
11
12public class Member ...{
13 private string _name;
14 
15 public Member() ...{}
16 public Member(string name) ...{
17 _name = name;
18 }
19 
20 public string Name ...{
21 get ...{ return _name;}
22 set ...{ _name = value;}
23 }
24
25 public override bool Equals(object obj) ...{
26 Member member = (Member)obj;
27 return (_name == member.Name) ? true : false;
28 }
29
30 public override int GetHashCode() ...{
31 return base.GetHashCode();
32 }
33
34 public static bool operator ==(Member member1, Member member2) ...{
35 return member1.Equals(member2) ? true : false;
36 }
37
38 public static bool operator !=(Member member1, Member member2) ...{
39 return !(member1 == member2);
40 }
41}
42
43public class Members : CollectionBase ...{
44 public Member this[int index] ...{
45 get ...{ return (Member)List[index]; }
46 set ...{ List[index] = value; }
47 }
48 
49 public int IndexOf(Member member) ...{
50 return this.List.IndexOf(member);
51 }
52 
53 public void Add(Member member) ...{
54 this.List.Add(member);
55 }
56
57 public void Remove(Member member) ...{
58 if (this.IndexOf(member) != -1)
59 List.Remove(member);
60 }
61}
62
63public class main ...{
64 public static void Main() ...{
65 Members members = new Members();
66
67 // insert
68 members.Add(new Member("Clare"));
69 members.Add(new Member("Jessie"));
70 members.Add(new Member("Jingyi"));
71
72 // modify
73 int index = members.IndexOf(new Member("Jessie"));
74 if (index != -1) members[index] = new Member("Cerlina");
75
76 // delete
77 members.Remove(new Member("Clare"));
78
79 // search
80 index = members.IndexOf(new Member("Jingyi"));
81 if (index != -1) members.RemoveAt(index);
82 
83 foreach(Member member in members) ...{
84 Console.WriteLine(member.Name);
85 }
86 }
87}
執行結果
在Member class中,25行到40行

public override bool Equals(object obj) ...{
Member member = (Member)obj;
return (_name == member.Name) ? true : false;
}

public override int GetHashCode() ...{
return base.GetHashCode();
}

public static bool operator ==(Member member1, Member member2) ...{
return member1.Equals(member2) ? true : false;
}

public static bool operator !=(Member member1, Member member2) ...{
return !(member1 == member2);
}整體的目標是為了改寫object的比較方式,在.NET,預設是用reference比較object是否相同,但這對Collection的IndexOf(),Remove()有很大的影響,所以我override了Equals()和GetHashCode(),並對==和!=做了operator overloading。
CollectionBase原本都有實現IndexOf(),Add(),Remove(),但因只針對Object而非Member,所以針對了Member overload了IndexOf(),Add(),Remove(),另外使用了indexer是為了方便Collection的使用。
.NET 2.0 (使用Collection<T>)
繼承Collection<Member>,因為是泛型,所以不用再overload IndexOf(),Add(),Remove(),也不用在定義indexer,因為泛型會直接使用Member,所以code非常精簡。
Collection<T>的架構頗複雜,implement了IEnumerable,IEnumerable<T>,ICollection,ICollection<T>,IList,IList<T>。


1/**//**//**//*
2(C) OOMusou 2007 http://oomusou.cnblogs.com
3
4Filename : BuildOwnCollection2.cs
5Compiler : Visual Studio 2005 / C# 2.0
6Description : Demo how to build strong typed collection
7Release : 06/19/2007 1.0
8*/
9using System;
10using System.Collections.ObjectModel;
11
12public class Member ...{
13 private string _name;
14
15 public Member() ...{ }
16 public Member(string name) ...{
17 _name = name;
18 }
19
20 public string Name ...{
21 get ...{ return _name; }
22 set ...{ _name = value; }
23 }
24
25 public override bool Equals(object obj) ...{
26 Member member = (Member)obj;
27 return (_name == member.Name) ? true : false;
28 }
29
30 public override int GetHashCode() ...{
31 return base.GetHashCode();
32 }
33
34 public static bool operator ==(Member member1, Member member2) ...{
35 return member1.Equals(member2) ? true : false;
36 }
37
38 public static bool operator !=(Member member1, Member member2) ...{
39 return !(member1 == member2);
40 }
41}
42
43public class Members : Collection<Member> ...{
44}
45
46public class main ...{
47 public static void Main() ...{
48 Members members = new Members();
49
50 // insert
51 members.Add(new Member("Clare"));
52 members.Add(new Member("Jessie"));
53 members.Add(new Member("Jingyi"));
54
55 // modify
56 int index = members.IndexOf(new Member("Jessie"));
57 if (index != -1) members[index] = new Member("Cerlina");
58
59 // delete
60 members.Remove(new Member("Clare"));
61
62 // search
63 index = members.IndexOf(new Member("Jingyi"));
64 if (index != -1) members.RemoveAt(index);
65
66 foreach (Member member in members) ...{
67 Console.WriteLine(member.Name);
68 }
69 }
70}
執行結果
Cerlina
35行

public class Members : Collection<Member>
{
}
非常精簡,只需繼承Collection<Member>即可。
繼承自List<T>也是可以。
不過List<T>的method較多,包含了不少適用於List<T>的算法,如BinarySearch(), Sort(), Reverse(),若用不到,會造成自訂Collection過於臃腫,較占內存。 若會用到這些算法,則應繼承於List<T>。
繼承於Collection<T>是剛剛好Collection會用到的method而已。
本文介绍如何在.NET中创建自定义的强类型集合类,包括继承CollectionBase和使用.NET 2.0的泛型Collection<T>两种方法。
12万+

被折叠的 条评论
为什么被折叠?



