Tải bản đầy đủ - 0 (trang)
Chapter 12.  Delegates and Events

Chapter 12.  Delegates and Events

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

presentstheuserinterfaceandwaitsfortheusertotakean

action.Theusermighttakemanydifferentactions,suchas

choosingamongmenuselections,pushingbuttons,updating

textfields,clickingicons,andsoforth.Eachactioncausesan

eventtoberaised.Othereventscanberaisedwithoutdirect

useraction,suchaseventsthatcorrespondtotimerticksofthe

internalclock,emailbeingreceived,file-copyoperations

completing,etc.

Aneventistheencapsulationoftheideathat"something

happened"towhichtheprogrammustrespond.Eventsand

delegatesaretightlycoupledconceptsbecauseflexibleevent

handlingrequiresthattheresponsetotheeventbedispatched

totheappropriateeventhandler.Aneventhandleristypically

implementedinC#viaadelegate.

Delegatesarealsousedascallbackssothatoneclasscansay

toanother"dothisworkandwhenyou'redone,letmeknow."



12.1.Delegates

InC#,delegatesarefirst-classobjects,fullysupportedbythe

language.Technically,adelegateisareferencetypeusedto

encapsulateamethodwithaspecificsignatureandreturntype.

[1]

Youcanencapsulateanymatchingmethodinthatdelegate.

[1]Ifthemethodisaninstancemethod,thedelegateencapsulatesthetargetobjectaswell.



InC++andmanyotherlanguages,youcantosomedegreeaccomplish

thisrequirementwithfunctionpointersandpointerstomember

functions.



Adelegateiscreatedwiththedelegatekeyword,followedbya

returntypeandthesignatureofthemethodsthatcanbe

delegatedtoit,asinthefollowing:

publicdelegateintWhichIsFirst(objectobj1,objectobj2);



ThisdeclarationdefinesadelegatenamedWhichIsFirst,which

willencapsulateanymethodthattakestwoobjectsas

parametersandthatreturnsanint.

Oncethedelegateisdefined,youcanencapsulateamember

methodwiththatdelegatebyinstantiatingthedelegate,

passinginamethodthatmatchesthereturntypeand

signature.Asanalternative,youcanuseanonymousmethods

asdescribedlater.Ineithercase,thedelegatecanthenbeused

toinvokethatencapsulatedmethod.



12.1.1.UsingDelegatestoSpecifyMethodsat

Runtime

Delegatesdecoupletheclassthatdeclaresthedelegatefrom

theclassthatusesthedelegate.Forexample,supposethatyou

wanttocreateasimplegenericcontainerclasscalledaPair

thatcanholdandsortanytwoobjectspassedtoit.Youcan't

knowinadvancewhatkindofobjectsaPairwillhold,butby

creatingmethodswithinthoseobjectstowhichthesortingtask

canbedelegated,youcandelegateresponsibilityfor

determiningtheirordertotheobjectsthemselves.

Differentobjectswillsortdifferently(forexample,aPairof

Counterobjectsmightsortinnumericorder,whileaPairof

Buttonsmightsortalphabeticallybytheirname).Astheauthor

ofthePairclass,youwanttheobjectsinthepairtohavethe

responsibilityofknowingwhichshouldbefirstandwhichshould

besecond.Toaccomplishthis,youwillinsistthattheobjectsto

bestoredinthePairmustprovideamethodthattellsyouhow

tosorttheobjects.

Youcandefinethisrequirementwithinterfaces,aswell.

Delegatesaresmallerandoffinergranularitythaninterfaces.

ThePairclassdoesn'tneedtoimplementanentireinterface,it

justneedstodefinethesignatureandreturntypeofthe

methoditwantstoinvoke.Thatiswhatdelegatesarefor:they

definethereturntypeandsignatureofmethodsthatcanbe

invokedthroughtheinterface.

Inthiscase,thePairclasswilldeclareadelegatenamed

WhichIsFirst.WhenthePairneedstoknowhowtoorderits

objects,itwillinvokethedelegatepassinginitstwomember

objectsasparameters.Theresponsibilityfordecidingwhichof

thetwoobjectscomesfirstisdelegatedtothemethod

encapsulatedbythedelegate:



publicdelegateComparison

WhichIsFirst(Tobj1,Tobj2)



Inthisdefinition,WhichIsFirstisdefinedtoencapsulatea

methodthattakestwoobjectsasparameters,andthatreturns

anobjectoftypeComparison.Comparisonturnsouttobean

enumerationyouwilldefine:

publicenumComparison

{

theFirstComesFirst=1,

theSecondComesFirst=2

}



Totestthedelegate,youwillcreatetwoclasses,aDogclass

andaStudentclass.DogsandStudentshavelittleincommon,

exceptthattheybothimplementmethodsthatcanbe

encapsulatedbyWhichComesFirst,andthusbothDogobjects

andStudentobjectsareeligibletobeheldwithinPairobjects.

Inthetestprogram,youwillcreateacoupleofStudentsanda

coupleofDogs,andstorethemeachinaPair.Youwillthen

createinstancesofWhichIsFirsttoencapsulatetheir

respectivemethodsthatwilldeterminewhichStudentorwhich

Dogobjectshouldbefirst,andwhichsecond.Let'stakethis

stepbystep.

YoubeginbycreatingaPairconstructorthattakestwoobjects

andstashesthemawayinaprivatearray:

publicPair(

TfirstObject,

TsecondObject)



{

thePair[0]=firstObject;

thePair[1]=secondObject;

}



Next,youoverrideToString()toobtainthestringvalueof

thetwoobjects:

publicoverridestringToString()

{

returnthePair[0].ToString()+","+

thePair[1].ToString();

}



YounowhavetwoobjectsinyourPairandyoucanprintout

theirvalues.You'rereadytosortthemandprinttheresultsof

thesort.Youcan'tknowinadvancewhatkindofobjectsyou

willhave,soyoudelegatetheresponsibilityofdecidingwhich

objectcomesfirstinthesortedPairtotheobjectsthemselves.

BoththeDogclassandtheStudentclassimplementmethods

thatcanbeencapsulatedbyWhichIsFirst.Anymethodthat

takestwoobjectsandreturnsaComparisoncanbe

encapsulatedbythisdelegateatruntime.

YoucannowdefinetheSort()methodforthePairclass:

publicvoidSort(WhichIsFirsttheDelegatedFunc)

{

if(theDelegatedFunc(thePair[0],thePair[1])==

Comparison.theSecondComesFirst)

{

Ttemp=thePair[0];



thePair[0]=thePair[1];

thePair[1]=temp;

}

}



Thismethodtakesaparameter:adelegateoftype

WhichIsFirstnamedtheDelegatedFunc.TheSort()method

delegatesresponsibilityfordecidingwhichofthetwoobjectsin

thePaircomesfirsttothemethodencapsulatedbythat

delegate.InthebodyoftheSort()method,itinvokesthe

delegatedmethodandexaminesthereturnvalue,whichwillbe

oneofthetwoenumeratedvaluesofComparison.

IfthevaluereturnedistheSecondComesFirst,theobjects

withinthepairareswapped;otherwisenoactionistaken.

Thisisanalogoustohowtheotherparameterswork.Ifyouhad

amethodthattookanintasaparameter:

intSomeMethod(intmyParam){//...}



theparameternameismyParam,butyoucanpassinanyint

valueorvariable.Similarly,theparameternameinthedelegate

exampleistheDelegatedFunc,butyoucanpassinanymethod

thatmeetsthereturnvalueandsignaturedefinedbythe

delegateWhichIsFirst.

ImagineyouaresortingStudentsbyname.Youwriteamethod

thatreturnstheFirstComesFirstifthefirststudent'sname

comesfirst,andtheSecondComesFirstifthesecondstudent's

namedoes.Ifyoupassin"Amy,Beth"themethodreturns

theFirstComesFirst,andifyoupassin"Beth,Amy"itreturns

theSecondComesFirst.IfyougetbacktheSecondComesFirst,



theSort()methodreversestheitemsinitsarray,settingAmy

tothefirstpositionandBethtothesecond.

Nowaddonemoremethod,ReverseSort(),whichforcesthe

itemsinthearrayintothereverseoftheirnormalorder:

publicvoidReverseSort(WhichIsFirsttheDelegatedFunc)

{

if(theDelegatedFunc(thePair[0],thePair[1])==

Comparison.theFirstComesFirst)

{

Ttemp=thePair[0];

thePair[0]=thePair[1];

thePair[1]=temp;

}

}



ThelogichereisidenticaltoSort(),exceptthatthismethod

performstheswapifthedelegatedmethodsaysthatthefirst

itemcomesfirst.Becausethedelegatedfunctionthinksthefirst

itemcomesfirst,andthisisareversesort,theresultyouwant

isfortheseconditemtocomefirst.Thistimeifyoupassin

"Amy,Beth,"thedelegatedfunctionreturns

theFirstComesFirst(i.e.,Amyshouldcomefirst),butbecause

thisisareversesort,itswapsthevalues,settingBethfirst.

Thisallowsyoutousethesamedelegatedfunctionasyouused

withSort(),withoutforcingtheobjecttosupportafunction

thatreturnsthereversesortedvalue.

Nowallyouneedaresomeobjectstosort.You'llcreatetwo

absurdlysimpleclasses:StudentandDog.AssignStudent

objectsanameatcreation:

publicclassStudent

{



publicStudent(stringname)

{

this.name=name;

}



TheStudentclassrequirestwomethods:onetooverride

ToString()andtheothertobeencapsulatedasthedelegated

method.

StudentmustoverrideToString()sothattheToString()

methodinPair,whichinvokesToString()onthecontained

objects,willworkproperly;theimplementationdoesnothing

morethanreturnthestudent'sname(whichisalreadyastring

object):

publicoverridestringToString()

{

returnname;

}



ItmustalsoimplementamethodtowhichPair.Sort()can

delegatetheresponsibilityofdeterminingwhichoftwoobjects

comesfirst:

return(String.Compare(s1.name,s2.name)<0?

Comparison.theFirstComesFirst:

Comparison.theSecondComesFirst);



String.Compare()isa.NETFrameworkmethodonthe

Stringclassthatcomparestwostringsandreturnslessthan

zeroifthefirstissmaller,greaterthanzeroifthesecondis



smaller,andzeroiftheyarethesame.Thismethodwas

discussedinsomedetailinChapter10.Noticethatthelogic

herereturnstheFirstComesFirstonlyifthefirststringis

smaller;iftheyarethesameorthesecondislarger,this

methodreturnstheSecondComesFirst.

NoticethattheWhichStudentComesFirst()methodtakestwo

objectsasparametersandreturnsaComparison.Thisqualifies

ittobeaPair.WhichIsFirstdelegatedmethod,whose

signatureandreturnvalueitmatches.

ThesecondclassisDog.Forourpurposes,Dogobjectswillbe

sortedbyweight,lighterdogsbeforeheavier.Here'sthe

completedeclarationofDog:

publicclassDog

{

publicDog(intweight)

{

this.weight=weight;

}

//dogsareorderedbyweight

publicstaticComparisonWhichDogComesFirst(

Objecto1,Objecto2)

{

Dogd1=(Dog)o1;

Dogd2=(Dog)o2;

returnd1.weight>d2.weight?

Comparison.theSecondComesFirst:

Comparison.theFirstComesFirst;

}

publicoverridestringToString()

{

returnweight.ToString();

}

privateintweight;



}



TheDogclassalsooverridesToStringandimplementsastatic

methodwiththecorrectsignatureforthedelegate.Noticealso

thattheDogandStudentdelegatemethodsdon'thavethe

samename.Theydon'tneedtohavethesamename,asthey

willbeassignedtothedelegatedynamicallyatruntime.



Youcancallyourdelegatedmethodnamesanythingyoulike,but

creatingparallelnames(forexample,WhichStudentComesFirstand

WhichDogComesFirst)makesthecodeeasiertoread,understand,and

maintain.



Example12-1isthecompleteprogram,whichillustrateshow

thedelegatemethodsareinvoked.



Example12-1.Workingwithdelegates

#regionUsingdirectives

usingSystem;

usingSystem.Collections.Generic;

usingSystem.Text;

#endregion

namespaceDelegates

{

publicenumComparison

{

theFirstComesFirst=1,



theSecondComesFirst=2

}

//asimplecollectiontohold2items

publicclassPair

{

//privatearraytoholdthetwoobjects

privateT[]thePair=newT[2];

//thedelegatedeclaration

publicdelegateComparison

WhichIsFirst(Tobj1,Tobj2);

//passedinconstructortaketwoobjects,

//addedinorderreceived

publicPair(

TfirstObject,

TsecondObject)

{

thePair[0]=firstObject;

thePair[1]=secondObject;

}

//publicmethodwhichordersthetwoobjects

//bywhatevercriteriatheobjectlikes!

publicvoidSort(

WhichIsFirsttheDelegatedFunc)

{

if(theDelegatedFunc(thePair[0],thePair[1])

==Comparison.theSecondComesFirst)

{

Ttemp=thePair[0];

thePair[0]=thePair[1];

thePair[1]=temp;

}

}



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

Chapter 12.  Delegates and Events

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

×