Should C # Methoden , die können statisch sein statisch sein?
Wir haben heute darüber gesprochen und ich bin irgendwie auf dem Zaun. Stellen Sie sich vor, Sie haben eine lange Methode, aus der Sie ein paar Zeilen herausarbeiten. Die neue Methode übernimmt wahrscheinlich einige lokale Variablen aus der übergeordneten Methode und gibt einen Wert zurück. Das bedeutet , es könnte statisch sein.
Die Frage ist: sollte es statisch sein? Es ist nicht statisch durch Design oder Auswahl, sondern einfach von Natur aus, da es keine Instanzwerte referenziert.
Antworten:
Es hängt davon ab, ob. Es gibt wirklich zwei Arten von statischen Methoden:
In einer kleinen bis mittleren Codebasis können Sie die beiden Methoden wirklich austauschbar behandeln.
Wenn Sie eine Methode in der ersten Kategorie haben (kann statisch sein) und diese ändern müssen, um auf den Klassenstatus zuzugreifen, ist es relativ einfach herauszufinden, ob es möglich ist, die statische Methode in eine Instanzmethode umzuwandeln.
In einer großen Codebasis kann es jedoch aufgrund der schieren Anzahl von Anrufstellen schwierig sein, zu suchen, ob es möglich ist, eine statische Methode in eine nicht statische umzuwandeln. Oft sehen die Leute die Anzahl der Anrufe und sagen "ok ... ich ändere diese Methode besser nicht, sondern erstelle eine neue, die das tut, was ich brauche".
Das kann entweder zu Folgendem führen:
Beide Dinge sind schlecht.
Mein Rat wäre also, dass ich bei einer Codebasis über 200 KB LOC Methoden nur dann statisch machen würde, wenn es sich um statische Methoden handelt.
Das Refactoring von nicht statisch zu statisch ist relativ einfach (fügen Sie einfach ein Schlüsselwort hinzu). Wenn Sie also später aus einer statischen Dose eine tatsächliche statische machen möchten (wenn Sie die Funktionalität außerhalb einer Instanz benötigen), können Sie dies. Das inverse Refactoring, bei dem eine statische Dose in eine Instanzmethode umgewandelt wird, ist jedoch VIEL teurer.
Bei großen Codebasen ist es besser, Fehler auf der Seite der einfachen Erweiterung zu machen, als auf der Seite der idealogischen Reinheit.
Machen Sie also bei großen Projekten die Dinge nicht statisch, es sei denn, Sie brauchen sie. Machen Sie bei kleinen Projekten einfach das, was Ihnen am besten gefällt.
quelle
Ich würde es nicht zu einem öffentlichen statischen Mitglied dieser Klasse machen . Der Grund dafür ist, dass die öffentliche Statik etwas über den Klassentyp aussagt: Nicht nur, dass "dieser Typ weiß, wie man dieses Verhalten ausführt", sondern auch "es liegt in der Verantwortung dieses Typs, dieses Verhalten auszuführen". Und wahrscheinlich hat das Verhalten keine wirkliche Beziehung mehr zum größeren Typ.
Das heißt aber nicht, dass ich es überhaupt nicht statisch machen würde. Fragen Sie sich Folgendes: Könnte die neue Methode logischerweise woanders hingehören? Wenn Sie darauf mit "Ja" antworten können, möchten Sie es wahrscheinlich statisch machen (und auch verschieben). Auch wenn das nicht stimmt, können Sie es dennoch statisch machen. Markiere es einfach nicht
public
.Der Einfachheit halber können Sie es zumindest markieren
internal
. Dadurch wird normalerweise vermieden, dass die Methode verschoben werden muss, wenn Sie keinen einfachen Zugriff auf einen geeigneteren Typ haben, sie jedoch bei Bedarf so zugänglich bleibt, dass sie nicht als Teil der öffentlichen Benutzeroberfläche für Benutzer Ihrer Klasse angezeigt wird .quelle
Nicht unbedingt.
Das Verschieben öffentlicher Methoden von statisch zu nicht statisch ist eine grundlegende Änderung und würde Änderungen an allen Anrufern oder Verbrauchern erfordern. Wenn eine Methode wie eine Instanzmethode erscheint, aber zufällig keine Instanzmitglieder verwendet, würde ich vorschlagen, sie als Maß für die Zukunftssicherheit zu einer Instanzmethode zu machen.
quelle
Ja. Der Grund "es kann statisch sein" ist, dass es nicht mit dem Zustand des Objekts arbeitet, für das es aufgerufen wird. Daher ist es keine Instanzmethode, sondern eine Klassenmethode. Wenn es das tun kann, was es tun muss, ohne jemals auf die Daten für die Instanz zuzugreifen, sollte es statisch sein.
quelle
Ja, das sollte es. Es gibt verschiedene Metriken für die Kopplung , die messen, wie Ihre Klasse von anderen Dingen abhängt, wie z. B. anderen Klassen, Methoden usw. Wenn Sie Methoden statisch machen, können Sie den Grad der Kopplung niedrig halten, da Sie sicher sein können, dass eine statische Methode keine referenziert Mitglieder.
quelle
Ich denke, es würde es ein bisschen lesbarer machen, wenn Sie es als statisch markieren ... Dann würde jemand, der mitkommt, wissen, dass es keine Instanzvariablen referenziert, ohne die gesamte Funktion lesen zu müssen ...
quelle
Persönlich bin ich ein großer Fan von Staatenlosigkeit. Benötigt Ihre Methode Zugriff auf den Status der Klasse? Wenn die Antwort nein ist (und es ist wahrscheinlich nein, sonst würden Sie nicht in Betracht ziehen, es zu einer statischen Methode zu machen), dann machen Sie es.
Kein Zugang zum Staat ist weniger Kopfschmerzen. So wie es eine gute Idee ist, private Mitglieder zu verstecken, die von anderen Klassen nicht benötigt werden, ist es eine gute Idee, den Staat vor Mitgliedern zu verstecken, die ihn nicht brauchen. Reduzierter Zugriff kann weniger Fehler bedeuten. Außerdem erleichtert es das Einfädeln, da es viel einfacher ist, statische Elemente threadsicher zu halten. Es gibt auch eine Leistungsüberlegung, da die Laufzeit keinen Verweis darauf als Parameter für statische Methoden übergeben muss.
Der Nachteil ist natürlich, dass Sie den Status ändern müssen, wenn Sie jemals feststellen, dass Ihre zuvor statische Methode aus irgendeinem Grund auf den Status zugreifen muss. Jetzt verstehe ich, dass dies ein Problem für öffentliche APIs sein kann. Wenn dies also eine öffentliche Methode in einer öffentlichen Klasse ist, sollten Sie vielleicht ein wenig über die Auswirkungen nachdenken. Trotzdem habe ich in der realen Welt noch nie eine Situation erlebt, in der dies tatsächlich ein Problem verursachte, aber vielleicht habe ich einfach Glück.
Also ja, machen Sie es auf jeden Fall.
quelle
Statische Methoden sind schneller als nicht statische. Ja, sie sollten statisch sein, wenn sie können, und es gibt keinen besonderen Grund , sie nicht statisch zu lassen .
quelle
Ich bin überrascht, dass so wenige hier tatsächlich die Kapselung erwähnen. Eine Instanzmethode hat automatisch Zugriff auf alle privaten (Instanz-) Felder, Eigenschaften und Methoden. Zusätzlich zu allen geschützten, die von Basisklassen geerbt wurden.
Wenn Sie Code schreiben, sollten Sie ihn so schreiben, dass Sie so wenig wie möglich verfügbar machen und dass Sie Zugriff auf so wenig wie möglich haben.
Ja, es könnte wichtig sein, Ihren Code schnell zu machen, was passieren würde, wenn Sie Ihre Methoden statisch machen. In der Regel ist es jedoch wichtiger, dass Ihr Code so unfähig ist, Fehler wie möglich zu erzeugen. Eine Möglichkeit, dies zu erreichen, besteht darin, dass Ihr Code Zugriff auf so wenig wie möglich von "privaten Dingen" hat.
Dies mag auf den ersten Blick irrelevant erscheinen, da das OP offensichtlich von Refactoring spricht, das in diesem Szenario nicht schief gehen und neue Fehler verursachen kann. Dieser refactored Code muss jedoch in Zukunft beibehalten und geändert werden, wodurch Ihr Code einen größeren "Angriff" erhält Oberfläche "in Bezug auf neue Fehler, wenn es Zugriff auf private Instanzmitglieder hat. Im Allgemeinen denke ich, dass die Schlussfolgerung hier lautet: "Ja, meistens sollten Ihre Methoden statisch sein", es sei denn, es gibt andere Gründe, warum sie nicht statisch sind. Und das einfach, weil es "die Kapselung und das Verstecken von Daten besser nutzt und" sichereren "Code erzeugt" ...
quelle
Es ist keine gute Idee, etwas statisch zu machen, nur weil man es kann. Statische Methoden sollten aufgrund ihres Designs statisch sein, nicht aufgrund von Zufällen.
Wie Michael sagte, wird eine spätere Änderung den Code beschädigen, der sie verwendet.
Trotzdem klingt es so, als würden Sie eine private Dienstprogrammfunktion für die Klasse erstellen, die tatsächlich statisch ist.
quelle
Wenn Sie in der Lage waren, einige Zeilen umzugestalten, und die resultierende Methode statisch sein könnte, ist dies wahrscheinlich ein Hinweis darauf, dass die Zeilen, die Sie aus dieser Methode herausgezogen haben, überhaupt nicht zur enthaltenden Klasse gehören, und Sie sollten in Betracht ziehen, sie zu verschieben ihre eigene Klasse.
quelle
Persönlich hätte ich keine andere Wahl, als es statisch zu machen. Resharper gibt in diesem Fall eine Warnung aus und unser PM hat die Regel "Keine Warnungen vom Resharper".
quelle
Es kommt darauf an, aber im Allgemeinen mache ich diese Methoden nicht statisch. Der Code ändert sich ständig und vielleicht möchte ich eines Tages diese Funktion virtuell machen und sie in einer Unterklasse überschreiben. Oder vielleicht muss es eines Tages auf Instanzvariablen verweisen. Es wird schwieriger sein, diese Änderungen vorzunehmen, wenn jede Anrufstelle geändert werden muss.
quelle
Ich schlage vor, dass der beste Weg, darüber nachzudenken, folgender ist: Wenn Sie eine Klassenmethode benötigen, die aufgerufen werden muss, wenn keine Instanzen der Klasse instanziiert werden oder einen globalen Status beibehalten, ist statisch eine gute Idee. Aber im Allgemeinen schlage ich vor, dass Sie es vorziehen sollten, Mitglieder nicht statisch zu machen.
quelle
Sie sollten über Ihre Methoden und Klassen nachdenken:
Wenn die letzten beiden "Ja" sind, sollte Ihre Methode / Klasse wahrscheinlich statisch sein.
Das am häufigsten verwendete Beispiel ist wahrscheinlich die
Math
Klasse. Jede wichtige OO-Sprache hat sie und alle Methoden sind statisch. Weil Sie sie überall und jederzeit verwenden können müssen, ohne eine Instanz zu erstellen.Ein weiteres gutes Beispiel ist die
Reverse()
Methode in C #.Dies ist eine statische Methode in der
Array
Klasse. Es kehrt die Reihenfolge Ihres Arrays um.Code:
Es wird nicht einmal etwas zurückgegeben, Ihr Array ist umgekehrt, da alle Arrays Instanzen der Array-Klasse sind.
quelle
Solange Sie die neue Methode privat statisch machen , ist dies keine bahnbrechende Änderung. Tatsächlich enthält FxCop diese Anleitung als eine seiner Regeln ( http://msdn.microsoft.com/en-us/library/ms245046(VS.80).aspx ) mit den folgenden Informationen:
Abgesehen davon fasst der erste Kommentar von David Kean die Bedenken prägnanter zusammen, indem er sagt, dass es tatsächlich mehr um die Richtigkeit als um den Leistungsgewinn geht:
quelle
Ich würde definitiv alles, was ich kann, aus einem anderen Grund in statische verwandeln:
Statische Funktionen werden bei JIT ohne "this" -Parameter aufgerufen. Dies bedeutet zum Beispiel, dass eine nicht statische Funktion mit 3 Parametern (Mitgliedsmethode) mit 4 Parametern auf dem Stapel verschoben wird.
Dieselbe Funktion, die als statische Funktion kompiliert wurde, würde mit 3 Parametern aufgerufen. Dies kann Register für die JIT freigeben und Stapelspeicherplatz sparen ...
quelle
Ich bin im Lager "nur private Methoden statisch machen". Das Erstellen einer öffentlichen Methode kann zu einer nicht gewünschten Kopplung führen und die Testbarkeit beeinträchtigen: Sie können eine öffentliche statische Methode nicht stubben.
Wenn Sie eine Methode testen möchten, die eine öffentliche statische Methode verwendet, testen Sie am Ende auch die statische Methode, die möglicherweise nicht Ihren Wünschen entspricht.
quelle
Inhärent statische Methoden, die aus irgendeinem Grund nicht statisch sind, sind einfach ärgerlich. Nämlich:
Ich rufe meine Bank an und frage nach meinem Guthaben.
Sie fragen nach meiner Kontonummer.
Meinetwegen. Instanzmethode.
Ich rufe meine Bank an und frage nach ihrer Postanschrift.
Sie fragen nach meiner Kontonummer.
WTF? Fail - sollte eine statische Methode gewesen sein.
quelle
Ich betrachte es allgemein aus einer funktionalen Perspektive reiner Funktionen. Muss es eine Instanzmethode sein? Wenn nicht, können Sie davon profitieren, wenn Sie den Benutzer zwingen, die Variablen zu übergeben, und den Status der aktuellen Instanz nicht beschädigen. (Nun, Sie könnten den Status immer noch entstellen, aber es geht darum, dies nicht zu tun.) Ich entwerfe Instanzmethoden im Allgemeinen als öffentliche Mitglieder und gebe mein Bestes, um private Mitglieder statisch zu machen. Bei Bedarf (Sie können sie später leichter in andere Klassen extrahieren.
quelle
In diesen Fällen tendiere ich dazu, die Methode in eine statische Bibliothek oder eine Utils-Bibliothek zu verschieben, sodass ich das Konzept des "Objekts" nicht mit dem Konzept der "Klasse" mische.
quelle