Anda di halaman 1dari 7

6/26/2015

ParameterpassinginC#

ParameterpassinginC#
ManypeoplehavebecomefairlyconfusedabouthowparametersarepassedinC#,particularlywithregardto
referencetypes.Thispageshouldhelptoclearupsomeofthatconfusion.Ifyouhaveanysuggestionsforhow
itcanbemadeclearer,pleasemailme.
Microsoftalsohasagoodpageaboutthistopic(whichIbelieveusesexactlythesameterminologyasthispage
letmeknowiftheyappeartodisagree).
Note:LeeRichardsonhaswrittenacomplementaryarticletothisone,particularlyforthosewholearnwellwith
pictures.Basicallyitillustratesthesamepoints,butusingprettydiagramstoshowwhat'sgoingon.

Tableofcontents
Preamble:whatisareferencetype?
Furtherpreamble:whatisavaluetype?
Checkingyouunderstandthepreamble...
Thedifferentkindsofparameters
Valueparameters
Referenceparameters
Outputparameters
Parameterarrays
Miniglossary

Preamble:whatisareferencetype?
In.NET(andthereforeC#)therearetwomainsortsoftype:referencetypesandvaluetypes.Classes,delegates
andinterfacesarereferencetypesstructsandenumsarevaluetypes.Theyactdifferently,andalotofconfusion
aboutparameterpassingisreallydowntopeoplenotproperlyunderstandingthedifferencebetweenthem.
Here'saquickexplanation:
Areferencetypeisatypewhichhasasitsvalueareferencetotheappropriatedataratherthanthedataitself.
Forinstance,considerthefollowingcode:
StringBuildersb=newStringBuilder();

(IhaveusedStringBuilderasarandomexampleofareferencetypethere'snothingspecialaboutit.)Here,we
declareavariablesb,createanewStringBuilderobject,andassigntosbareferencetotheobject.Thevalueof
sbisnottheobjectitself,it'sthereference.Assignmentinvolvingreferencetypesissimplethevaluewhichis
assignedisthevalueoftheexpression/variablei.e.thereference:
StringBuilderfirst=newStringBuilder();
first.Append("hello");
StringBuildersecond=first;
Console.WriteLine(second);//Printshello

Herewedeclareavariablefirst,createanewStringBuilderobject,andassigntofirstareferencetothe
object.Wethenassigntosecondthevalueoffirst.Thismeansthattheybothrefertothesameobject.Ifwe
modifythecontentsoftheobjectviaanothercalltofirst.Append,thatchangeisvisibleviasecond:
StringBuilderfirst=newStringBuilder();
first.Append("hello");
StringBuildersecond=first;
first.Append("world");
Console.WriteLine(second);//Printshelloworld

http://jonskeet.uk/csharp/parameters.html

1/7

6/26/2015

ParameterpassinginC#

Theyarestill,however,independentvariablesthemselves.Changingthevalueoffirsttorefertoacompletely
differentobject(orindeedchangingthevaluetoanullreference)doesn'taffectsecondatall,ortheobjectit
refersto:
StringBuilderfirst=newStringBuilder();
first.Append("hello");
StringBuildersecond=first;
first.Append("world");
first=newStringBuilder("goodbye");
Console.WriteLine(first);//Printsgoodbye
Console.WriteLine(second);//Stillprintshelloworld

Toreiterate:classtypes,interfacetypes,delegatetypesandarraytypesareallreferencetypes.

Furtherpreamble:whatisavaluetype?
Whilereferencetypeshavealayerofindirectionbetweenthevariableandtherealdata,valuetypesdon't.
Variablesofavaluetypedirectlycontainthedata.Assignmentofavaluetypeinvolvestheactualdatabeing
copied.Takeasimplestruct,forexample:
publicstructIntHolder
{
publicinti;
}

WhereverthereisavariableoftypeIntHolder,thevalueofthatvariablecontainsallthedatainthiscase,the
singleintegervalue.Anassignmentcopiesthevalue,asdemonstratedhere:
IntHolderfirst=newIntHolder();
first.i=5;
IntHoldersecond=first;
first.i=6;
Console.WriteLine(second.i);

(Downloadsamplecode)Output:
5

Here,second.ihasthevalue5,becausethat'sthevaluefirst.ihaswhentheassignmentsecond=first
occursthevaluesinsecondareindependentofthevaluesinfirstapartfromwhentheassignmenttakesplace.
Simpletypes(suchasfloat,int,char),enumtypesandstructtypesareallvaluetypes.
Notethatmanytypes(suchasstring)appearinsomewaystobevaluetypes,butinfactarereferencetypes.
Theseareknownasimmutabletypes.Thismeansthatonceaninstancehasbeenconstructed,itcan'tbe
changed.Thisallowsareferencetypetoactsimilarlytoavaluetypeinsomewaysinparticular,ifyouholda
referencetoanimmutableobject,youcanfeelcomfortableinreturningitfromamethodorpassingittoanother
method,safeintheknowledgethatitwon'tbechangedbehindyourback.Thisiswhy,forinstance,the
string.Replacedoesn'tchangethestringitiscalledon,butreturnsanewinstancewiththenewstringdatain
iftheoriginalstringwerechanged,anyothervariablesholdingareferencetothestringwouldseethechange,
whichisveryrarelywhatisdesired.
Contrastthiswithamutable(changeable)typesuchasArrayListifamethodreturnstheArrayListreference
storedinaninstancevariable,thecallingcodecouldthenadditemstothelistwithouttheinstancehavingany
sayaboutit,whichisusuallyaproblem.Havingsaidthatimmutablereferencetypesactlikevaluetypes,they
arenotvaluetypes,andshouldn'tbethoughtofasactuallybeingvaluetypes.
Formoreinformationaboutvaluetypes,referencetypes,andwherethedataforeachisstoredinmemory,
pleaseseemyotherarticleaboutthesubject.
http://jonskeet.uk/csharp/parameters.html

2/7

6/26/2015

ParameterpassinginC#

Checkingyouunderstandthepreamble...
WhatwouldyouexpecttoseefromthecodeaboveifthedeclarationoftheIntHoldertypewasasaclass
insteadofastruct?Ifyoudon'tunderstandwhytheoutputwouldbe6,pleaserereadbothpreamblesandmail
meifit'sstillnotclearifyoudon'tgetit,it'smyfault,notyours,andIneedtoimprovethispage.Ifyoudo
understandit,parameterpassingbecomesveryeasytounderstandreadon.

Thedifferentkindsofparameters
TherearefourdifferentkindsofparametersinC#:valueparameters(thedefault),referenceparameters(which
usetherefmodifier),outputparameters(whichusetheoutmodifier),andparameterarrays(whichusethe
paramsmodifier).Youcanuseanyofthemwithbothvalueandreferencetypes.Whenyouhearthewords
"reference"or"value"used(orusethemyourself)youshouldbeveryclearinyourownmindwhetheryou
meanthataparameterisareferenceorvalueparameter,orwhetheryoumeanthatthetypeinvolvedisa
referenceorvaluetype.Ifyoucankeepthetwoideasseparated,they'reverysimple.

Valueparameters
Bydefault,parametersarevalueparameters.Thismeansthatanewstoragelocationiscreatedforthevariable
inthefunctionmemberdeclaration,anditstartsoffwiththevaluethatyouspecifyinthefunctionmember
invocation.Ifyouchangethatvalue,thatdoesn'talteranyvariablesinvolvedintheinvocation.Forinstance,if
wehave:
voidFoo(StringBuilderx)
{
x=null;
}
...
StringBuildery=newStringBuilder();
y.Append("hello");
Foo(y);
Console.WriteLine(y==null);

(Downloadsamplecode)Output:
False

Thevalueofyisn'tchangedjustbecausexissettonull.Rememberthoughthatthevalueofareferencetype
variableisthereferenceiftworeferencetypevariablesrefertothesameobject,thenchangestothedatain
thatobjectwillbeseenviabothvariables.Forexample:
voidFoo(StringBuilderx)
{
x.Append("world");
}
...
StringBuildery=newStringBuilder();
y.Append("hello");
Foo(y);
Console.WriteLine(y);

(Downloadsamplecode)Output:
helloworld
http://jonskeet.uk/csharp/parameters.html

3/7

6/26/2015

ParameterpassinginC#

AftercallingFoo,theStringBuilderobjectthatyreferstocontains"helloworld",asinFoothedata"world"was
appendedtothatobjectviathereferenceheldinx.
Nowconsiderwhathappenswhenvaluetypesarepassedbyvalue.AsIsaidbefore,thevalueofavaluetype
variableisthedataitself.UsingthepreviousdefinitionofthestructIntHolder,let'swritesomecodesimilarto
theabove:
voidFoo(IntHolderx)
{
x.i=10;
}
...
IntHoldery=newIntHolder();
y.i=5;
Foo(y);
Console.WriteLine(y.i);

(Downloadsamplecode)Output:
5

WhenFooiscalled,xstartsoffasastructwithvaluei=5.Itsivalueisthenchangedto10.Fooknowsnothing
aboutthevariabley,andafterthemethodcompletes,thevalueinywillbeexactlythesameasitwasbefore(i.e.
5).
Aswedidearlier,checkthatyouunderstandwhatwouldhappenifIntHolderwasdeclaredasaclassinsteadof
astruct.Youshouldunderstandwhyy.iwouldbe10aftercallingFoointhatcase.

Referenceparameters
Referenceparametersdon'tpassthevaluesofthevariablesusedinthefunctionmemberinvocationtheyuse
thevariablesthemselves.Ratherthancreatinganewstoragelocationforthevariableinthefunctionmember
declaration,thesamestoragelocationisused,sothevalueofthevariableinthefunctionmemberandthevalue
ofthereferenceparameterwillalwaysbethesame.Referenceparametersneedtherefmodifieraspartofboth
thedeclarationandtheinvocationthatmeansit'salwaysclearwhenyou'repassingsomethingbyreference.
Let'slookatourpreviousexamples,justchangingtheparametertobeareferenceparameter:
voidFoo(refStringBuilderx)
{
x=null;
}
...
StringBuildery=newStringBuilder();
y.Append("hello");
Foo(refy);
Console.WriteLine(y==null);

(Downloadsamplecode)Output:
True

Here,becauseareferencetoyispassedratherthanitsvalue,changestothevalueofparameterxare
immediatelyreflectediny.Intheaboveexample,yendsupbeingnull.Comparethiswiththeresultofthe
samecodewithouttherefmodifiers.
Nowconsiderthestructcodewehadearlier,butusingreferenceparameters:
http://jonskeet.uk/csharp/parameters.html

4/7

6/26/2015

ParameterpassinginC#

voidFoo(refIntHolderx)
{
x.i=10;
}
...
IntHoldery=newIntHolder();
y.i=5;
Foo(refy);
Console.WriteLine(y.i);

(Downloadsamplecode)Output:
10

Thetwovariablesaresharingastoragelocation,sochangestoxarealsovisiblethroughy,soy.ihasthevalue
10attheendofthiscode.

Sidenote:whatisthedifferencebetweenpassingavalueobjectbyreferenceand
areferenceobjectbyvalue?
Youmayhavenoticedthatthelastexample,passingastructbyreference,hadthesameeffectin
thiscodeaspassingaclassbyvalue.Thisdoesn'tmeanthatthey'rethesamething,however.
Considerthefollowingcode:
voidFoo(???IntHolderx)
{
x=newIntHolder();
}
...
IntHoldery=newIntHolder();
y.i=5;
Foo(???y);

ConsiderthecasewhereIntHolderisastruct(i.e.avaluetype)andtheparameterisareference
parameter(i.e.replace???withrefabove).AfterthecalltoFoo(refy),thevalueofyisanew
IntHoldervaluei.e.y.iis0.
InthecasewhereIntHolderisaclass(i.e.areferencetype)andtheparameterisavalueparameter
(i.e.remove???above),thevalueofyisn'tchangedit'sareferencetothesameobjectitwas
beforethefunctionmembercall.Thisdifferenceisabsolutelycrucialtounderstanding
parameterpassinginC#,andiswhyIbelieveitishighlyconfusingtosaythatobjectsare
passedbyreferencebydefaultinsteadofthecorrectstatementthatobjectreferencesare
passedbyvaluebydefault.

Outputparameters
Likereferenceparameters,outputparametersdon'tcreateanewstoragelocation,butusethestoragelocationof
thevariablespecifiedontheinvocation.Outputparametersneedtheoutmodifieraspartofboththedeclaration
andtheinvocationthatmeansit'salwaysclearwhenyou'repassingsomethingasanoutputparameter.
Outputparametersareverysimilartoreferenceparameters.Theonlydifferencesare:
Thevariablespecifiedontheinvocationdoesn'tneedtohavebeenassignedavaluebeforeitispassedto
thefunctionmember.Ifthefunctionmembercompletesnormally,thevariableisconsideredtobe
assignedafterwards(soyoucanthen"read"it).
http://jonskeet.uk/csharp/parameters.html

5/7

6/26/2015

ParameterpassinginC#

Theparameterisconsideredinitiallyunassigned(inotherwords,youmustassignitavaluebeforeyou
can"read"itinthefunctionmember).
Theparametermustbeassignedavaluebeforethefunctionmembercompletesnormally.
Hereissomeexamplecodeshowingthis,withanintparameter(intisavaluetype,butifyouunderstood
referenceparametersproperly,youshouldbeabletoseewhatthebehaviourforreferencetypesis):
voidFoo(outintx)
{
//Can'treadxhereit'sconsideredunassigned
//Assignmentthismusthappenbeforethemethodcancompletenormally
x=10;
//Thevalueofxcannowberead:
inta=x;
}
...
//Declareavariablebutdon'tassignavaluetoit
inty;
//Passitinasanoutputparameter,eventhoughitsvalueisunassigned
Foo(outy);
//It'snowassignedavalue,sowecanwriteitout:
Console.WriteLine(y);

(Downloadsamplecode)Output:
10

Parameterarrays
Parameterarraysallowavariablenumberofargumentstobepassedintoafunctionmember.Thedefinitionof
theparameterhastoincludetheparamsmodifier,buttheuseoftheparameterhasnosuchkeyword.A
parameterarrayhastocomeattheendofthelistofparameters,andmustbeasingledimensionalarray.When
usingthefunctionmember,anynumberofparameters(includingnone)mayappearintheinvocation,solongas
theparametersareeachcompatiblewiththetypeoftheparameterarray.Alternatively,asinglearraymaybe
passed,inwhichcasetheparameteractsjustasanormalvalueparameter.Forexample:
voidShowNumbers(paramsint[]numbers)
{
foreach(intxinnumbers)
{
Console.Write(x+"");
}
Console.WriteLine();
}
...
int[]x={1,2,3};
ShowNumbers(x);
ShowNumbers(4,5);

(Downloadsamplecode)Output:
123
45

http://jonskeet.uk/csharp/parameters.html

6/7

6/26/2015

ParameterpassinginC#

Inthefirstinvocation,thevalueofthevariablexispassedbyvalue,asthetypeofxisalreadyanarray.Inthe
secondinvocation,anewarrayofintsiscreatedcontainingthetwovaluesspecified,andareferencetothis
arrayispassed(stillbyvalue).

Miniglossary
Someinformaldefinitionsandsummariesofterms:
Functionmember
Afunctionmemberisamethod,property,event,indexer,userdefinedoperator,instanceconstructor,
staticconstructor,ordestructor.
Outputparameter
Aparameterverysimilartoareferenceparameter,butwithdifferentdefiniteassignmentrules.
Referenceparameter(passbyreferencesemantics)
Aparameterwhichsharesthestoragelocationofthevariableusedinthefunctionmemberinvocation.As
theysharethesamestoragelocation,theyalwayshavethesamevalue(sochangingtheparametervalue
changestheinvocationvariablevalue).
Referencetype
Typewherethevalueofavariable/expressionofthattypeisareferencetoanobjectratherthantheobject
itself.
Storagelocation
Aportionofmemoryholdingthevalueofavariable.
Valueparameter(thedefaultsemantics,whicharepassbyvalue)
Avalueparameterthathasitsownstoragelocation,andthusitsownvalue.Theinitialvalueisthevalue
oftheexpressionusedinthefunctionmemberinvocation.
Valuetype
Typewherethevalueofavariable/expressionofthattypeistheobjectdataitself.
Variable
Nameassociatedwithastoragelocationandtype.(Usuallyasinglevariableisassociatedwithastorage
location.Theexceptionsareforreferenceandoutputparameters.)

Instructor Led Classes With Exam Fees Included In The


Price, Call Us

Net
Class

aardvark-training.com
C#Download

C#Example

C#Code

C#ClassTutorial

Backtothemainpage.

http://jonskeet.uk/csharp/parameters.html

7/7

Anda mungkin juga menyukai