Freigeben über


Parameterentwurf

Hinweis

Dieser Inhalt wird mit Genehmigung von Pearson Education, Inc. aus Framework Design Guidelines: Konventionen, Idiome und Muster für wiederverwendbare .NET-Bibliotheken, 2. Auflage nachgedruckt. Diese Ausgabe wurde 2008 veröffentlicht, und das Buch wurde seitdem in der dritten Ausgabe vollständig überarbeitet. Einige der Informationen auf dieser Seite sind möglicherweise veraltet.

Dieser Abschnitt enthält allgemeine Richtlinien für den Parameterentwurf, einschließlich Abschnitte mit Richtlinien zum Überprüfen von Argumenten. Darüber hinaus sollten Sie sich auf die Richtlinien beziehen, die unter "Benennungsparameter" beschrieben sind.

✔️ Verwenden Sie den am wenigsten abgeleiteten Parametertyp, der die vom Element erforderliche Funktionalität bereitstellt.

Angenommen, Sie möchten eine Methode entwerfen, die eine Auflistung aufzählt und jedes Element in der Konsole druckt. Eine solche Methode sollte IEnumerable als Parameter verwenden, nicht ArrayList oder IList, beispielsweise.

❌ Verwenden Sie keine reservierten Parameter.

Wenn in einer zukünftigen Version mehr Eingaben für ein Mitglied erforderlich sind, kann eine neue Überladung hinzugefügt werden.

❌ VERMEIDEN SIE öffentlich zugängliche Methoden, die Zeiger, Arrays von Zeigern oder mehrdimensionale Arrays als Parameter verwenden.

Zeiger und mehrdimensionale Arrays sind relativ schwer zu verwenden. In fast allen Fällen können APIs neu gestaltet werden, um diese Typen nicht als Parameter zu verwenden.

✔️ Platzieren Sie alle out-Parameter nach allen Wert- und ref-Parametern (mit Ausnahme von Parameterarrays). Das gilt selbst dann, wenn dies zu einer inkonsistenten Parameterreihenfolge zwischen Überladungen führt (siehe Überladen von Membern).

Die out Parameter können als zusätzliche Rückgabewerte betrachtet werden, und das Gruppieren dieser Parameter erleichtert das Verständnis der Methodensignatur.

✔️ Befolgen Sie beim Überschreiben von Membern oder Implementieren von Schnittstellenmembern eine einheitliche Parameterbenennung.

Dadurch wird die Beziehung zwischen den Methoden besser kommuniziert.

Auswahl zwischen Enum- und booleschen Parametern

✔️ Verwenden Sie Enums, wenn ein Member sonst zwei oder mehr boolesche Parameter hätte.

❌ Verwenden Sie keine Booleans, es sei denn, Sie sind absolut sicher, dass es niemals mehr als zwei Werte geben wird.

Enumerationen bieten Ihnen raum für zukünftiges Hinzufügen von Werten, aber Sie sollten sich alle Auswirkungen des Hinzufügens von Werten zu Enumerationen bewusst sein, die im Enumerationsentwurf beschrieben werden.

✔️ ERWÄGEN SIE die Verwendung von Booleans für Konstruktorparameter, die wirklich Zwei-Zustand-Werte sind und einfach zum Initialisieren von booleschen Eigenschaften verwendet werden.

Überprüfen von Argumenten

✔️ Überprüfen Sie Argumente, die an öffentliche, geschützte oder explizit implementierte Member übergeben werden. Lösen Sie System.ArgumentException oder eine zugehörige Unterklasse aus, wenn bei der Überprüfung ein Fehler auftritt.

Beachten Sie, dass die eigentliche Überprüfung nicht unbedingt im öffentlichen oder geschützten Member selbst erfolgen muss. Es könnte auf einer niedrigeren Ebene in einigen privaten oder internen Routinen passieren. Der Hauptpunkt ist, dass der gesamte Oberflächenbereich, der den Endbenutzern ausgesetzt ist, die Argumente überprüft.

✔️ Lösen Sie ArgumentNullException aus, wenn ein NULL-Argument übergeben wird und der Member keine NULL-Argumente unterstützt.

✔️ Überprüfen Sie Enumerationsparameter.

Gehen Sie nicht davon aus, dass Enum-Argumente innerhalb des durch das Enum definierten Bereichs liegen. Die CLR ermöglicht selbst dann das Umwandeln beliebiger ganzzahliger Werte in Enumerationswerte, wenn der Wert nicht in der Enumeration definiert ist.

❌ Verwenden Sie NICHT Enum.IsDefined, um Enumerationsbereiche zu überprüfen.

✔️ Beachten Sie, dass sich veränderbare Argumente möglicherweise geändert haben, nachdem sie überprüft wurden.

Wenn das Mitglied sicherheitsempfindlich ist, werden Sie aufgefordert, eine Kopie zu erstellen und dann das Argument zu überprüfen und zu verarbeiten.

Parameterübergabe

Aus Sicht eines Framework-Designers gibt es drei Hauptgruppen von Parametern: By-Value-Parameter, ref Parameter und out Parameter.

Wenn ein Argument über einen By-Value-Parameter übergeben wird, empfängt das Element eine Kopie des tatsächlich übergebenen Arguments. Wenn es sich bei dem Argument um einen Werttyp handelt, wird eine Kopie des Arguments auf dem Stapel platziert. Wenn es sich bei dem Argument um einen Verweistyp handelt, wird eine Kopie des Verweises auf dem Stapel platziert. Die meisten gängigen CLR-Sprachen, z. B. C#, VB.NET und C++, übergeben standardmäßig Parameter nach Wert.

Wenn ein Argument über einen ref Parameter übergeben wird, empfängt das Element einen Verweis auf das tatsächliche übergebene Argument. Wenn das Argument ein Werttyp ist, wird ein Verweis auf das Argument im Stapel platziert. Wenn das Argument ein Referenztyp ist, wird ein Verweis auf die Referenz auf den Stack gelegt. Ref Parameter können verwendet werden, um dem Member das Ändern von Argumenten zu ermöglichen, die vom Aufrufer übergeben werden.

Out Parameter ähneln ref Parametern mit einigen kleinen Unterschieden. Der Parameter wird anfänglich als nicht zugewiesen betrachtet und kann im Member erst gelesen werden, wenn ihm ein Wert zugewiesen wird. Außerdem muss dem Parameter ein Wert zugewiesen werden, bevor das Element zurückgegeben wird.

❌ VERMEIDEN Sie die Verwendung out oder ref Parameter.

Die Verwendung der out oder ref Parameter erfordert Erfahrung mit Zeigern, das Verständnis, wie sich Werttypen und Referenztypen unterscheiden, und die Fähigkeit, Methoden mit mehreren Rückgabewerten zu handhaben. Auch mit dem Unterschied zwischen out- und ref-Parametern ist nicht jeder vertraut. Frameworkarchitekten, die für ein allgemeines Publikum entwerfen, sollten nicht erwarten, dass Benutzer in der Arbeit mit out oder ref Parametern vertraut werden.

❌ Übergeben Sie Verweistypen NICHT nach Verweis.

Es gibt einige begrenzte Ausnahmen für die Regel, z. B. eine Methode, die zum Austauschen von Verweisen verwendet werden kann.

Mitglieder mit variabler Anzahl von Parametern

Elemente, die eine variable Anzahl von Argumenten annehmen können, werden durch Angeben eines Arrayparameters ausgedrückt. Stellt beispielsweise String die folgende Methode bereit:

public class String {
    public static string Format(string format, object[] parameters);
}

Ein Benutzer kann dann die String.Format Methode wie folgt aufrufen:

String.Format("File {0} not found in {1}",new object[]{filename,directory});

Durch Hinzufügen des C#-Params-Schlüsselworts zu einem Arrayparameter wird der Parameter in einen sogenannten Params-Array-Parameter geändert und eine Abkürzung zum Erstellen eines Arrays für temporäre Nutzung bereitgestellt.

public class String {
    public static string Format(string format, params object[] parameters);
}

Auf diese Weise kann der Benutzer die Methode aufrufen, indem die Arrayelemente direkt in der Argumentliste übergeben werden.

String.Format("File {0} not found in {1}",filename,directory);

Beachten Sie, dass das Schlüsselwort params nur dem letzten Parameter in der Parameterliste hinzugefügt werden kann.

✔️ ERWÄGEN Sie, das Params-Schlüsselwort zu Arrayparametern hinzuzufügen, wenn Sie erwarten, dass die Endbenutzer Arrays mit einer kleinen Anzahl von Elementen übergeben. Wenn erwartet wird, dass viele Elemente in gängigen Szenarien übergeben werden, werden die Benutzer diese Elemente wahrscheinlich trotzdem nicht inline übergeben, und daher ist das Schlüsselwort "Params" nicht erforderlich.

❌ VERMEIDEN Sie die Verwendung von Paramsarrays, wenn der Aufrufer fast immer die Eingabe bereits in einem Array hat.

Member mit Bytearrayparametern werden z. B. fast nie aufgerufen, indem einzelne Bytes übergeben werden. Aus diesem Grund verwenden Bytearrayparameter in .NET Framework nicht das Params-Schlüsselwort.

❌ Verwenden Sie KEINE params-Arrays, wenn das Array vom Member geändert wird, der den params-Arrayparameter verwendet.

Aufgrund der Tatsache, dass viele Compiler die Argumente an das Element in ein temporäres Array an der Aufrufwebsite umwandeln, kann das Array ein temporäres Objekt sein, und daher gehen alle Änderungen am Array verloren.

✔️ Ziehen Sie die Verwendung des params-Schlüsselworts auch dann bei einer einfachen Überladung in Betracht, wenn es von einer komplexeren Überladung nicht verwendet werden könnte.

Fragen Sie sich, ob Benutzer es schätzen würden, das params-Array in einer Überladung zu haben, auch wenn es nicht in allen Überladungen enthalten ist.

✔️ VERSUCHEN Sie, Parameter zu sortieren, um die Verwendung des Schlüsselworts params zu ermöglichen.

✔️ ERWÄGEN SIE, spezielle Überladungen und Codepfade für Aufrufe mit einer geringen Anzahl von Argumenten in extrem leistungsempfindlichen APIs bereitzustellen.

Dies ermöglicht es, das Erstellen von Arrayobjekten zu vermeiden, wenn die API mit einer kleinen Anzahl von Argumenten aufgerufen wird. Bilden Sie die Namen der Parameter, indem Sie eine Singularform des Arrayparameters verwenden und ein numerisches Suffix hinzufügen.

Dies sollten Sie nur tun, wenn Sie den gesamten Codepfad speziell behandeln, nicht nur ein Array erstellen und die allgemeine Methode aufrufen.

✔️ BEACHTEN Sie, dass NULL als Paramsarray-Argument übergeben werden kann.

Sie sollten überprüfen, ob das Array vor der Verarbeitung nicht NULL ist.

❌ Verwenden Sie NICHT die varargs-Methoden, die auch als Ellipse bezeichnet werden.

Einige CLR-Sprachen, z. B. C++, unterstützen eine alternative Konvention zum Übergeben von Variablenparameterlisten, die als Methoden bezeichnet werden varargs . Die Konvention sollte nicht in Frameworks verwendet werden, da sie nicht CLS-kompatibel ist.

Zeigerparameter

Im Allgemeinen sollten Zeiger nicht im öffentlichen Oberflächenbereich eines gut gestalteten verwalteten Codeframeworks angezeigt werden. Üblicherweise sollten Zeiger gekapselt werden. In einigen Fällen sind jedoch Zeiger aus Interoperabilitätsgründen erforderlich, und die Verwendung von Zeigern in solchen Fällen ist angemessen.

✔️ Da Zeiger nicht CLS-kompatibel sind, muss für Member mit Zeigerargumenten eine Alternative bereitgestellt werden.

❌ VERMEIDEN Sie eine teure Argumentüberprüfung von Zeigerargumenten.

✔️ Befolgen Sie beim Entwerfen von Membern mit Zeigern die gängigen Konventionen für Zeiger.

Beispielsweise ist es nicht erforderlich, den Startindex zu übergeben, da einfache Zeigerarithmetik verwendet werden kann, um dasselbe Ergebnis zu erzielen.

© Teile 2005, 2009 Microsoft Corporation. Alle Rechte vorbehalten.

Nachdruck mit freundlicher Genehmigung von Pearson Education, Inc., aus dem Buch Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition von Krzysztof Cwalina und Brad Abrams, veröffentlicht am 22. Oktober 2008 von Addison-Wesley Professional als Teil der Microsoft Windows Development Series.

Siehe auch