(原創) 如何建立自己的Collection? (.NET) (C#) (C++/CLI) (C/C++)
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已經幫我們做好了。
C#
/* 2
(C) OOMusou 2007 http://oomusou.cnblogs.com3

4
Filename : BuildOwnCollection1.cs5
Compiler : Visual Studio 2005 / C# 2.06
Description : Demo how to build strong typed collection 7
Release : 06/19/2007 1.08
*/9
using System;10
using System.Collections;11

12
public 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

43
public 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

63
public 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
// modify73
int index = members.IndexOf(new Member("Jessie"));74
if (index != -1) members[index] = new Member("Cerlina");75

76
// delete77
members.Remove(new Member("Clare"));78

79
// search80
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
}
執行結果
Cerlina
在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的使用。
C++/CLI
/* 2
(C) OOMusou 2007 http://oomusou.cnblogs.com3

4
Filename : BuildOwnCollection1.cpp5
Compiler : Visual C++ 8.0 / C++/CLI6
Description : Demo how to build strong typed collection 7
Release : 06/19/2007 1.08
*/9
#include "stdafx.h"10

11
using namespace System;12
using namespace System::Collections;13

14
public ref class Member {15
private:16
String^ _name;17
18
public:19
Member() {}20
Member(String^ name) {21
_name = name;22
}23
24
property String^ Name {25
String^ get() { return _name;}26
void set(String^ value) { _name = value; }27
}28

29
virtual bool Equals(Object^ obj) override {30
Member^ member = safe_cast<Member^>(obj);31
return (_name == member->Name) ? true : false;32
}33

34
virtual int GetHashCode() override {35
return Object::GetHashCode();36
}37

38
static bool operator==(Member^ member1, Member^ member2) {39
return member1->Equals(member2) ? true : false;40
}41

42
static bool operator!=(Member^ member1, Member^ member2) {43
return !(member1 == member2);44
}45
};46

47
public ref class Members : CollectionBase {48
public:49
property Member^ default[int] {50
Member^ get(int index) { return safe_cast<Member^>(List[index]); }51
void set(int index, Member^ value) { List[index] = safe_cast<Member^>(value); }52
}53
54
int IndexOf(Member^ member) {55
return this->List->IndexOf(member);56
}57
58
void Add(Member^ member) {59
this->List->Add(member);60
}61

62
void Remove(Member^ member) {63
if (this->IndexOf(member) != -1) 64
List->Remove(member);65
}66
};67

68
int main() {69
Members^ members = gcnew Members;70
71
// insert 72
members->Add(gcnew Member("Clare"));73
members->Add(gcnew Member("Jessie"));74
members->Add(gcnew Member("Jingyi"));75
76
// modify77
int index = members->IndexOf(gcnew Member("Jessie"));78
if (index != -1) 79
members[index] = gcnew Member("Cerlina");80

81
// delete82
members->Remove(gcnew Member("Clare"));83

84
// search85
index = members->IndexOf(gcnew Member("Jingyi"));86
if (index != -1) members->RemoveAt(index);87
88
for each(Member^ member in members)89
Console::WriteLine(member->Name);90
}
執行結果
Cerlina
.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>。
C#
/* 2
(C) OOMusou 2007 http://oomusou.cnblogs.com3

4
Filename : BuildOwnCollection2.cs5
Compiler : Visual Studio 2005 / C# 2.06
Description : Demo how to build strong typed collection 7
Release : 06/19/2007 1.08
*/9
using System;10
using System.Collections.ObjectModel;11

12
public 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

43
public class Members : Collection<Member> {44
}45

46
public class main {47
public static void Main() {48
Members members = new Members();49

50
// insert51
members.Add(new Member("Clare"));52
members.Add(new Member("Jessie"));53
members.Add(new Member("Jingyi"));54

55
// modify56
int index = members.IndexOf(new Member("Jessie"));57
if (index != -1) members[index] = new Member("Cerlina");58

59
// delete60
members.Remove(new Member("Clare"));61

62
// search63
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>即可。
C++/CLI
/* 2
(C) OOMusou 2007 http://oomusou.cnblogs.com3

4
Filename : BuildOwnCollection2.cpp5
Compiler : Visual C++ 8.0 / C++/CLI6
Description : Demo how to build strong typed collection by Generics7
Release : 06/19/2007 1.08
*/9
#include "stdafx.h"10

11
using namespace System;12
using namespace System::Collections::ObjectModel;13

14
public ref class Member {15
private:16
String^ _name;17

18
public:19
Member() { }20
Member(String^ name) {21
_name = name;22
}23

24
public:25
property String^ Name {26
String^ get() { return _name; }27
void set(String^ value) { _name = value; }28
}29

30
virtual bool Equals(Object^ obj) override {31
Member^ member = safe_cast<Member^>(obj);32
return (_name == member->Name) ? true : false;33
}34

35
virtual int GetHashCode() override {36
return Object::GetHashCode();37
}38

39
static bool operator ==(Member^ member1, Member^ member2) {40
return member1->Equals(member2) ? true : false;41
}42

43
static bool operator !=(Member^ member1, Member^ member2) {44
return !(member1 == member2);45
}46
};47

48
public ref class Members : Collection<Member^> {49
};50

51
int main() {52
Members^ members = gcnew Members;53

54
// insert55
members->Add(gcnew Member("Clare"));56
members->Add(gcnew Member("Jessie"));57
members->Add(gcnew Member("Jingyi"));58

59
// modify60
int index = members->IndexOf(gcnew Member("Jessie"));61
if (index != -1) members[index] = gcnew Member("Cerlina");62

63
// delete64
members->Remove(gcnew Member("Clare"));65

66
// search67
index = members->IndexOf(gcnew Member("Jingyi"));68
if (index != -1) members->RemoveAt(index);69

70
for each (Member^ member in members) {71
Console::WriteLine(member->Name);72
}73
}
執行結果
Cerlina
Conclusion
泛型最基本的應用,也是最原始的應用,就是在container,若用OO,只能用多型(多態)的技術,讓container放Object type,進Container須轉型成Object,出Container需再轉回各type,若用泛型,就可直接將各type放進container,不需轉型,不只速度提升,且code也非常的精簡。


浙公网安备 33010602011771号