Tải bản đầy đủ - 0 (trang)
Chapter 16. Collection Interfaces and Types

Chapter 16. Collection Interfaces and Types

Tải bản đầy đủ - 0trang

16.1TheCollectionInterfaces

Everycollectionhascertainsharedcharacteristics,whicharecapturedby

thecollectioninterfaces.The.NETFrameworkprovidesstandard

interfacesforenumerating,comparing,andcreatingcollections.

Chapter14introducedinterfaces,whichcreateacontractthata

classcanfulfill.Implementinganinterfaceallowsclientsofthe

classtoknowexactlywhattoexpectfromtheclass.



Byimplementingthecollectioninterfaces,yourcustomclassprovidesthe

samesemanticsasthecollectionclassesavailablethroughthe.NET

Framework.Table16-1liststhekeycollectioninterfacesandtheiruses.

Table16-1.Thecollectioninterfaces

Interface



Purpose



IEnumerable



Enumeratesthroughacollectionusingaforeach

statement



IEnumerator



Iteratesoveracollectionandsupportstheforeachloop



ICollection



Implementedbyallcollections



IComparer



Comparestwoobjects;usedforsorting



IList



Usedbycollectionsthatcanbeindexed



IDictionary



Forkey/value-basedcollectionssuchasHashtableand

SortedList



IDictionaryEnumerator



Allowsenumerationwithforeachofacollectionthat

supportsIDictionary



ThischapterwillfocusontheIEnumerableinterface,usingitto

demonstratehowyoucanimplementthecollectioninterfacesinyourown

classestoallowclientstotreatyourcustomclassesasiftheywere

collections.Forexample,youmightcreateacustomclassnamed

ListBoxTest.YourListBoxTestwillhaveasetofstringstobedisplayed.

YoucanimplementthecollectioninterfacesinyourListBoxTestclassto

allowclientstotreatyourListBoxTestasifitwereacollection.Thisallows

clientstoaddtotheListBoxTestusingtheindexoperator(e.g.,

myListBox[5]="NewString"),tosorttheListBoxTest,to

enumeratetheelementsoftheListBoxTest,andsoforth.



16.1.1TheIEnumerableInterface

Inthepreviouschapter,youdevelopedasimpleListBoxTestclassthat

providedanindexerforarray-likesemantics.Thatis,yourListBoxTest

implementeditsownindexersothatyoucouldtreattheListBoxTest

objectlikeitwasanArray:

myListBoxTest[5]="Helloworld";

stringtheText=myListBoxTest[1];

Ofcourse,ListBoxTestisnotanarray;itisjustacustomclassthatcan

betreatedlikeanarraybecauseyougaveitthisindexer.Youcanmake

yourListBoxTestclassevenmorelikearealarraybyprovidingsupport

foriteratingoverthecontentsofthearrayusingtheforeachstatement.

Toprovidesupportfortheforeachstatement,you'llneedtoimplement

theIEnumerableinterface.

Whenyouiterateoveranarrayyouvisiteachmemberinturn.



Programmerstalkaboutiteratingoveranarray,iteratingthe

array,iteratingthroughthearray,andenumeratingthearray.All

ofthesetermsmeanthesamething.



Theforeachstatementwillworkwithanyclassthatimplementsthe

IEnumerableinterface.ClassesthatimplementtheIEnumerableinterface

haveasinglemethod,GetEnumerator(),thatreturnsanobjectthat

implementsasecondinterface,IEnumerator.

Notethesubtledifferenceinthenamesofthesetwointerfaces.

IEnumerablevs.IEnumerator.Theformerdesignatesaclass

thatcanbeenumerated,thelatterdesignatesaclassthatdoes

theactualenumeraion.



TheentirejoboftheIEnumerableinterfaceistodefinethe

GetEnumerator()method.ThejoboftheGetEnumerator()methodisto

generateanenumeratorthatis,aninstanceofaclassthatimplements

theIEnumeratorinterface.

ByimplementingtheIEnumerableinterface,yourListBoxTestclassis

saying"youcanenumeratemymembers,justaskmeformy

enumerator."TheclientaskstheListBoxTestforitsenumeratorbycalling

theGetEnumerator()method.Whatitgetsbackisaninstanceofaclass

thatknowshowtoiterateoveralistbox.Thatclass,ListBoxEnumerator,

willimplementtheIEnumeratorinterface.

Thisgetsabitconfusing,solet'suseanexample.Whenyouimplement

theIEnumerableinterfaceforListBoxTest,youarepromisingpotential

clientsthatListBoxTestwillsupportenumeration.Thatallowsclientsof

yourListBoxTestclasstowritecodelikethis:

foreach(stringsinListBoxTest){//...}

YouimplementIEnumerablebyprovidingtheGetEnumerator()method,

whichreturnsanimplementationofIEnumerator.Inthiscase,you'll

returnaninstanceofListBoxEnumerator,andListBoxEnumeratorwill



implementtheIEnumeratorinterface:

publicIEnumeratorGetEnumerator()

{

return(IEnumerator)newListBoxEnumerator(this);

}

TheListBoxEnumeratorisaspecializedinstanceofIEnumeratorthat

knowshowtoenumeratethecontentsofyourListBoxTestclass.Notice

twothingsaboutthisimplementation.First,theconstructorfor

ListBoxEnumeratortakesasingleargument,andyoupassinthethis

reference.DoingsopassesinareferencetothecurrentListBoxTest

object,whichistheobjectthatwillbeenumerated.Second,noticethat

theListBoxEnumeratoriscasttoanIEnumeratorbeforeitisreturned.

ThiscastissafebecausetheListBoxEnumeratorclassimplementsthe

IEnumeratorinterface.

Analternativetocreatingaspecializedclasstoimplement

IEnumeratoristohavetheenumerableclass(ListBoxTest)

implementIEnumeratoritself.Inthatcase,theIEnumerator

returnedbyGetEnumeratorwouldbetheListBoxTestobject,

casttoIEnumerator.

Puttingtheenumerationresponsibilityintoadedicatedclass

thatimplementsIEnumerator(ListBoxEnumerator)isgenerally

preferredtothealternativeoflettingthecollectionclass

(ListBoxTest)knowhowtoenumerateitself.Thespecialized

enumerationclassencapsulatestheresponsibilityof

enumerationandthecollectionclass(ListBoxTest)isnot

clutteredwithalotofenumerationcode.



BecauseListBoxEnumeratorisspecializedtoknowonlyhowto

enumerateListBoxTestobjects(andnotanyotherenumerableobjects),

makeListBoxEnumeratoraprivateclass,containedwithinthedefinition



ofListBoxTest.ThecompletelistingisshowninExample16-1,followed

byadetailedanalysis.

Example16-1.Enumeration

usingSystem;



namespaceEnumeration

{

usingSystem;

usingSystem.Collections;



//implementsIEnumerable

publicclassListBoxTest:IEnumerable

{

privatestring[]strings;

privateintctr=0;



//privatenestedimplementationofListBoxEnumerator

privateclassListBoxEnumerator:IEnumerator

{



//memberfieldsofthenestedListBoxEnumeratorcl

privateListBoxTestcurrentListBox;

privateintindex;



//publicwithintheprivateimplementation

//thus,privatewithinListBoxTest



publicListBoxEnumerator(ListBoxTestcurrentListBox

{

//aparticularListBoxTestinstanceis

//passedin,holdareferencetoit

//inthemembervariablecurrentListBox.

this.currentListBox=currentListBox;

index=-1;

}



//Incrementtheindexandmakesurethe

//valueisvalid

publicboolMoveNext()



{

index++;

if(index>=currentListBox.strings.Length)

returnfalse;

else

returntrue;

}



publicvoidReset()

{

index=-1;

}



//Currentpropertydefinedasthe

//laststringaddedtothelistbox

publicobjectCurrent

{

get

{



return(currentListBox[index]);

}

}

}//endnestedclass



//Enumerableclassescanreturnanenumerator

publicIEnumeratorGetEnumerator()

{

return(IEnumerator)newListBoxEnumerator(this);

}



//initializethelistboxwithstrings

publicListBoxTest(paramsstring[]initialStrings)

{

//allocatespaceforthestrings

strings=newString[8];



//copythestringspassedintotheconstructor



foreach(stringsininitialStrings)

{

strings[ctr++]=s;

}

}



//addasinglestringtotheendofthelistbox

publicvoidAdd(stringtheString)

{

strings[ctr]=theString;

ctr++;

}



//allowarray-likeaccess

publicstringthis[intindex]

{

get

{

if(index<0||index>=strings.Length)



{

//handlebadindex

}

returnstrings[index];

}

set

{

strings[index]=value;

}

}



//publishhowmanystringsyouhold

publicintGetNumEntries()

{

returnctr;

}



}



classTester

{

publicvoidRun()

{

//createanewlistboxandinitialize

ListBoxTestcurrentListBox=

newListBoxTest("Hello","World");



//addafewstrings

currentListBox.Add("Who");

currentListBox.Add("Is");

currentListBox.Add("John");

currentListBox.Add("Galt");



//testtheaccess

stringsubst="Universe";

currentListBox[1]=subst;



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Chapter 16. Collection Interfaces and Types

Tải bản đầy đủ ngay(0 tr)

×