Parameterdesign
Kommentar
Det här innehållet skrivs om med behörighet från Pearson Education, Inc. från Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition. Den utgåvan publicerades 2008, och boken har sedan dess reviderats helt i den tredje utgåvan. En del av informationen på den här sidan kan vara inaktuell.
Det här avsnittet innehåller allmänna riktlinjer för parameterdesign, inklusive avsnitt med riktlinjer för att kontrollera argument. Dessutom bör du läsa riktlinjerna som beskrivs i Namngivningsparametrar.
✔️ Använd den minsta härledda parametertypen som tillhandahåller de funktioner som krävs av medlemmen.
Anta till exempel att du vill utforma en metod som räknar upp en samling och skriver ut varje objekt till konsolen. En sådan metod bör till exempel ta IEnumerable som parameter, inte ArrayList eller IList.
❌ Använd INTE reserverade parametrar.
Om det behövs mer indata till en medlem i någon framtida version kan en ny överlagring läggas till.
❌ HA INTE offentligt exponerade metoder som tar pekare, matriser med pekare eller flerdimensionella matriser som parametrar.
Pekare och flerdimensionella matriser är relativt svåra att använda korrekt. I nästan alla fall kan API:er göras om för att undvika att dessa typer tas som parametrar.
✔️ Placera alla out
parametrar efter alla bivärden och ref
parametrar (exklusive parametermatriser), även om det resulterar i en inkonsekvens i parameterordningen mellan överlagringar (se Överlagring av medlemmar).
Parametrarna out
kan ses som extra returvärden och om du grupperar dem tillsammans blir metodsignaturen lättare att förstå.
✔️ Var konsekvent när du namnger parametrar när du åsidosättar medlemmar eller implementerar gränssnittsmedlemmar.
Detta kommunicerar bättre relationen mellan metoderna.
Välja mellan uppräkningsparametrar och booleska parametrar
✔️ Använd uppräkningar om en medlem annars skulle ha två eller flera booleska parametrar.
❌ Använd INTE booleska värden om du inte är helt säker på att det aldrig kommer att finnas något behov av fler än två värden.
Uppräkningar ger dig lite utrymme för framtida tillägg av värden, men du bör vara medveten om alla konsekvenser av att lägga till värden i uppräkningar, som beskrivs i Uppräkningsdesign.
✔️ ÖVERVÄG att använda booleska värden för konstruktorparametrar som verkligen är tvåtillståndsvärden och som helt enkelt används för att initiera booleska egenskaper.
Verifiera argument
✔️ VERIFIERA argument som skickas till offentliga, skyddade eller uttryckligen implementerade medlemmar. Kasta System.ArgumentException, eller någon av dess underklasser, om verifieringen misslyckas.
Observera att den faktiska valideringen inte nödvändigtvis måste ske i den offentliga eller skyddade medlemmen själv. Det kan hända på en lägre nivå i någon privat eller intern rutin. Huvudpunkten är att hela ytan som exponeras för slutanvändarna kontrollerar argumenten.
✔️ ArgumentNullException Kasta om ett null-argument skickas och medlemmen inte stöder null-argument.
✔️ VERIFIERA uppräkningsparametrar.
Anta inte att uppräkningsargumenten ligger i det intervall som definieras av uppräkningen. CLR tillåter att alla heltalsvärden omvandlas till ett uppräkningsvärde även om värdet inte har definierats i uppräkningen.
❌ Använd Enum.IsDefined INTE för uppräkningsintervallkontroller.
✔️ Tänk på att föränderliga argument kan ha ändrats när de har verifierats.
Om medlemmen är säkerhetskänslig uppmanas du att göra en kopia och sedan validera och bearbeta argumentet.
Skicka parameter
Ur ett ramverksdesigners perspektiv finns det tre huvudgrupper med parametrar: parametrar, ref
parametrar och out
parametrar per värde.
När ett argument skickas via en bivärdesparameter får medlemmen en kopia av det faktiska argumentet som skickas in. Om argumentet är en värdetyp placeras en kopia av argumentet på stacken. Om argumentet är en referenstyp placeras en kopia av referensen på stacken. De mest populära CLR-språken, till exempel C#, VB.NET och C++, är standard för att skicka parametrar efter värde.
När ett argument skickas via en ref
parameter får medlemmen en referens till det faktiska argumentet som skickas in. Om argumentet är en värdetyp placeras en referens till argumentet på stacken. Om argumentet är en referenstyp placeras en referens till referensen på stacken. Ref
parametrar kan användas för att tillåta medlemmen att ändra argument som skickas av anroparen.
Out
parametrar liknar ref
parametrar, med några små skillnader. Parametern anses ursprungligen vara otilldelat och kan inte läsas i medlemstexten innan den tilldelas något värde. Dessutom måste parametern tilldelas ett visst värde innan medlemmen returnerar.
❌ UNDVIK användning out
eller ref
parametrar.
Användning out
eller ref
parametrar kräver erfarenhet av pekare, förståelse för hur värdetyper och referenstyper skiljer sig åt och hanteringsmetoder med flera returvärden. Dessutom är skillnaden mellan out
och ref
parametrar inte allmänt förstådd. Ramverksarkitekter som utformar för en allmän målgrupp bör inte förvänta sig att användarna ska bli skickliga på att arbeta med out
eller ref
parametrar.
❌ Skicka INTE referenstyper efter referens.
Det finns vissa begränsade undantag till regeln, till exempel en metod som kan användas för att växla referenser.
Medlemmar med variabelt antal parametrar
Medlemmar som kan ta ett variabelt antal argument uttrycks genom att ange en matrisparameter. Tillhandahåller till exempel String följande metod:
public class String {
public static string Format(string format, object[] parameters);
}
En användare kan sedan anropa String.Format metoden enligt följande:
String.Format("File {0} not found in {1}",new object[]{filename,directory});
Om du lägger till nyckelordet C# params i en matrisparameter ändras parametern till en så kallad params-matrisparameter och ger en genväg till att skapa en tillfällig matris.
public class String {
public static string Format(string format, params object[] parameters);
}
På så sätt kan användaren anropa metoden genom att skicka matriselementen direkt i argumentlistan.
String.Format("File {0} not found in {1}",filename,directory);
Observera att nyckelordet params endast kan läggas till i den sista parametern i parameterlistan.
✔️ ÖVERVÄG att lägga till nyckelordet params i matrisparametrar om du förväntar dig att slutanvändarna skickar matriser med ett litet antal element. Om det förväntas att många element skickas i vanliga scenarier kommer användarna förmodligen inte att skicka dessa element infogade ändå, så nyckelordet params är inte nödvändigt.
❌ UNDVIK att använda params-matriser om anroparen nästan alltid skulle ha indata redan i en matris.
Till exempel skulle medlemmar med bytematrisparametrar nästan aldrig anropas genom att skicka enskilda byte. Därför använder inte bytematrisparametrar i .NET Framework nyckelordet params.
❌ Använd INTE params-matriser om matrisen ändras av medlemmen som tar parametern paramsmatris.
Eftersom många kompilatorer omvandlar argumenten till medlemmen till en tillfällig matris på anropsplatsen kan matrisen vara ett tillfälligt objekt och därför går alla ändringar i matrisen förlorade.
✔️ ÖVERVÄG att använda nyckelordet params i en enkel överlagring, även om en mer komplex överlagring inte kunde använda den.
Fråga dig själv om användarna skulle värdera att ha params-matrisen i en överlagring även om den inte var i alla överlagringar.
✔️ Försök att beställa parametrar för att göra det möjligt att använda nyckelordet params.
✔️ ÖVERVÄG att tillhandahålla särskilda överlagringar och kodsökvägar för anrop med ett litet antal argument i extremt prestandakänsliga API:er.
Detta gör det möjligt att undvika att skapa matrisobjekt när API:et anropas med ett litet antal argument. Skapa namnen på parametrarna genom att ta en enskild form av matrisparametern och lägga till ett numeriskt suffix.
Du bör bara göra detta om du ska specialfalla hela kodsökvägen, inte bara skapa en matris och anropa den mer allmänna metoden.
✔️ Tänk på att null kan skickas som ett params-matrisargument.
Du bör kontrollera att matrisen inte är null före bearbetning.
❌ Använd INTE metoderna varargs
, även kallat ellipsen.
Vissa CLR-språk, till exempel C++, stöder en alternativ konvention för att skicka variabelparameterlistor som kallas varargs
metoder. Konventionen bör inte användas i ramverk eftersom den inte är CLS-kompatibel.
Pekarparametrar
I allmänhet bör pekare inte visas i den offentliga ytan i ett väl utformat hanterat kodramverk. För det mesta bör pekare kapslas in. I vissa fall krävs dock pekare av samverkansskäl, och det är lämpligt att använda pekare i sådana fall.
✔️ Ange ett alternativ för alla medlemmar som tar ett pekarargument, eftersom pekare inte är CLS-kompatibla.
❌ UNDVIK att göra dyr argumentkontroll av pekarargument.
✔️ Följ vanliga pekarrelaterade konventioner när du utformar medlemmar med pekare.
Det finns till exempel inget behov av att skicka startindexet, eftersom enkel pekararitmetik kan användas för att uppnå samma resultat.
Portioner © 2005, 2009 Microsoft Corporation. Med ensamrätt.
Reprinted by permission of Pearson Education, Inc. from Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition by Krzysztof Cwalina and Brad Abrams, publicerad 22 okt 2008 av Addison-Wesley Professional som en del av Microsoft Windows Development Series.