Parameterentwurf
Hinweis
Diese Inhalte wurden mit Genehmigung von Pearson Education, Inc. aus Framework Design Guidelines nachgedruckt: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition. 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 zum Parameterentwurf, darunter u. a. Abschnitte zum Überprüfen von Argumenten. Darüber hinaus sollten Sie die Richtlinien unter Benennen von Parametern lesen.
✔️ Verwenden Sie den am wenigsten abgeleiteten Parametertyp, der die für den Member erforderliche Funktionalität bereitstellt.
Angenommen, Sie möchten eine Methode entwerfen, um eine Auflistung zu erstellen und die einzelnen Elemente in der Konsole zu veröffentlichen. Eine solche Methode sollte z. B. nicht ArrayList oder IList, sondern IEnumerable als Parameter verwenden.
❌ Reservierte Parameter sollten NICHT verwendet werden.
Wenn in einer zukünftigen Version weitere Eingaben für ein Member erforderlich sind, kann eine neue Überladung hinzugefügt werden.
❌ Öffentlich verfügbar gemachte Methoden mit Zeigern, Zeigerarrays oder mehrdimensionalen Arrays als Parameter sollten NICHT verwendet werden.
Die ordnungsgemäße Verwendung von Zeigern und mehrdimensionalen Arrays ist relativ kompliziert. In fast allen Fällen können APIs umgestaltet werden, damit diese Arten von Parametern vermieden werden.
✔️ 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. Durch die Gruppierung dieser Parameter wird die Methodensignatur verständlicher.
✔️ Befolgen Sie beim Überschreiben von Membern oder Implementieren von Schnittstellenmembern eine einheitliche Parameterbenennung.
Dadurch wird die Beziehung zwischen den Methoden besser erkennbar.
Auswählen zwischen Enumerations- und booleschen Parametern
✔️ Verwenden Sie Enumerationsparameter, wenn ein Member anderenfalls über zwei oder mehr boolesche Parameter verfügt.
❌ Boolesche Parameter sollten NUR DANN verwendet werden, wenn Sie ganz sicher sind, dass zu keinem Zeitpunkt mehr als zwei Werte benötigt werden.
Enumerationsparameter bieten die Möglichkeit, in der Zukunft Werte hinzufügen. Sie sollten sich jedoch der Auswirkungen beim Hinzufügen von Werten zu Enumerationsparametern bewusst sein. Diese sind unter Enum-Entwurf beschrieben.
✔️ Die Verwendung von booleschen Parametern sollte für Konstruktorparameter in Betracht gezogen werden, bei denen es sich um Werte mit zwei Zuständen handelt, die lediglich 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. Sie könnte auch auf einer unteren Ebene in einer privaten oder internen Routine durchgeführt werden. Entscheidend ist, dass die Argumente im gesamten Oberflächenbereich überprüft werden, der für Endbenutzer verfügbar gemacht wird.
✔️ 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 sich Enumerationsargumente innerhalb des von der Enumeration definierten Bereichs befinden. 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 änderbare Argumente nach der Überprüfung möglicherweise geändert wurden.
Bei Membern mit hohen Sicherheitsanforderungen sollten Sie eine Kopie erstellen und dann das Argument überprüfen und verarbeiten.
Parameterübergabe
Aus Sicht eines Frameworkdesigners sind drei Hauptgruppen von Parameters verfügbar: Wertparameter, ref
-Parameter und out
-Parameter.
Wenn ein Argument über einen Wertparameter übergeben wird, empfängt der Member eine Kopie des eigentlichen Arguments. Wenn das Argument vom Werttyp ist, wird eine Kopie des Arguments zum Stapel hinzugefügt. Handelt es sich um einen Verweistyp, wird eine Kopie des Verweises zum Stapel hinzugefügt. Die gängigsten CLR-Sprachen wie C#, VB.NET und C++ übergeben Parameter standardmäßig nach Wert.
Wenn ein Argument über einen ref
-Parameter übergeben wird, empfängt der Member einen Verweis auf das eigentliche Argument. Wenn das Argument vom Werttyp ist, wird ein Verweis auf das Argument zum Stapel hinzugefügt. Handelt es sich um einen Verweistyp, wird ein Verweis auf den Verweis zum Stapel hinzugefügt. Ref
-Parameter können verwendet werden, um Membern das Ändern von Argumenten zu ermöglichen, die vom Aufrufer übergeben werden.
Out
-Parameter sind mit ref
-Parametern vergleichbar und unterscheiden sich lediglich in einigen wenigen Aspekten. Der Parameter wird anfänglich als nicht zugewiesen betrachtet und kann im Member erst gelesen werden, wenn ihm ein Wert zugewiesen wird. Darüber hinaus muss dem Parameter vor der Memberrückgabe ein Wert zugewiesen werden.
❌out
- oder ref
-Parameter sollten nicht verwendet werden.
Die Verwendung von out
- oder ref
-Parametern erfordert Erfahrung im Umgang mit Zeigern, Kenntnisse der Unterschiede zwischen Wert- und Verweistypen sowie Erfahrung im Umgang mit Methoden mit mehreren Rückgabewerten. Auch mit dem Unterschied zwischen out
- und ref
-Parametern ist nicht jeder vertraut. Frameworkarchitekten, die für eine allgemeine Zielgruppe entwerfen, sollten nicht erwarten, dass Benutzer das Arbeiten mit out
- oder ref
-Parametern beherrschen.
❌ Übergeben Sie Verweistypen NICHT nach Verweis.
Für diese Regel gelten einige wenige Ausnahmen, wie z. B. eine Methode, die zum Austausch von Verweisen verwendet werden kann.
Member mit einer variablen Anzahl von Parametern
Member mit einer variablen Anzahl von Argumenten werden mit einem Arrayparameter ausgedrückt. Mit String wird z. B. die folgende Methode angegeben:
public class String {
public static string Format(string format, object[] parameters);
}
Ein Benutzer kann die String.Format-Methode wie folgt aufrufen:
String.Format("File {0} not found in {1}",new object[]{filename,directory});
Durch das Hinzufügen des C#-params-Schlüsselworts zu einem Arrayparameter wird der Parameter in einen sogenannten params-Arrayparameter geändert, der eine Verknüpfung zum Erstellen eines temporären Arrays bietet.
public class String {
public static string Format(string format, params object[] parameters);
}
Dadurch 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 params-Schlüsselwort nur zum letzten Parameter in der Parameterliste hinzugefügt werden kann.
✔️ Ziehen Sie das Hinzufügen des params-Schlüsselworts zu Arrayparametern in Betracht, wenn Sie davon ausgehen, dass die Endbenutzer Arrays mit einer geringen Anzahl von Elementen übergeben. Wenn davon ausgegangen wird, dass in den meisten Szenarien eine große Anzahl von Elementen übergeben wird, übergeben Benutzer diese Elemente wahrscheinlich nicht inline, sodass das params-Schlüsselwort nicht erforderlich ist.
❌ Vermeiden Sie die Verwendung von params-Arrays, wenn der Aufrufer in fast allen Szenarien bereits im Array über die Eingabe verfügt.
Member mit Bytearrayparametern werden z. B. fast nie aufgerufen, indem einzelne Bytes übergeben werden. Aus diesem Grund wird das params-Schlüsselwort nicht von Bytearrayparametern im .NET Framework verwendet.
❌ Verwenden Sie KEINE params-Arrays, wenn das Array vom Member geändert wird, der den params-Arrayparameter verwendet.
Da viele Compiler die Argumente für den Member beim Aufruf in ein temporäres Array umwandeln, kann das Array ein temporäres Objekt sein. Änderungen am Array gehen somit 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.
Überlegen Sie, ob Benutzer vom params-Array in einer Überladung profitieren würden, selbst wenn es nicht in allen Überladungen vorhanden wäre.
✔️ Versuchen Sie, Parameter so zu verwenden, dass eine Verwendung des params-Schlüsselworts möglich ist.
✔️ Ziehen Sie die Verwendung spezieller Überladungen und Codepfade für Aufrufe mit einer geringen Anzahl von Argumenten in äußerst leistungsabhängigen APIs in Betracht.
Dadurch kann das Erstellen von Arrayobjekten verhindert werden, wenn die API mit einer geringen Anzahl von Argumenten aufgerufen wird. Wählen Sie zur Benennung der Parameter die Singularform des Arrayparameters, und fügen Sie ein numerisches Suffix an.
Dieser Schritt sollte nur ausgeführt werden, wenn Sie den gesamten Codepfad als Sonderfall betrachten und nicht nur ein Array erstellen und die allgemeinere Methode aufrufen.
✔️ Beachten Sie, dass NULL als params-Arrayargument übergeben werden könnte.
Überprüfen Sie vor der Verarbeitung, dass das Array nicht NULL ist.
❌ Verwenden Sie NICHT die varargs
-Methoden, die auch als Ellipse bezeichnet werden.
Einige CLR-Sprachen wie C++ unterstützen eine alternative Konvention für die Übergabe von variablen Parameterlisten, die sogenannten varargs
-Methoden. Diese Konvention sollte in Frameworks nicht verwendet werden, da sie nicht CLS-kompatibel ist.
Zeigerparameter
Im Allgemeinen sollten Zeiger bei einem durchdachten verwalteten Codeframework nicht auf dem öffentlichen Oberflächenbereich erscheinen. In den meisten Fällen sollten Zeiger gekapselt werden. In einigen Fällen können Zeiger jedoch erforderlich sein, um Interoperabilität zu bieten. In diesen Szenarien ist die Verwendung von Zeigern angebracht.
✔️ Da Zeiger nicht CLS-kompatibel sind, muss für Member mit Zeigerargumenten eine Alternative bereitgestellt werden.
❌ Vermeiden Sie eine aufwendige Ü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. Stattdessen kann eine einfache Zeigerarithmetik verwendet werden, um dasselbe Ergebnis zu erreichen.
Teile ©2005, 2009 Microsoft Corporation. Alle Rechte vorbehalten.
Nachdruck mit Genehmigung von Pearson Education, Inc aus 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 durch Addison-Wesley Professional als Teil der Microsoft Windows Development Series.