Sollten C # -Methoden, die statisch sein können, statisch sein? [geschlossen]

103

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.

Bernhard Hofmann
quelle
1
Ziemlich genaues Duplikat von stackoverflow.com/questions/169378/…
JasonTrue
41
"ziemlich genau" ist ein Oxymoron
Matt Briggs
1
Resharper , das Visual Studio-Tool von Tools, sagt ja! :-)
Rebecca
@Junto Vielleicht in Ihrer Version, aber meine sagt, kann statisch gemacht werden ...
Robbie Dee

Antworten:

59

Es hängt davon ab, ob. Es gibt wirklich zwei Arten von statischen Methoden:

  1. Methoden, die statisch sind, weil sie sein können
  2. Methoden, die statisch sind, weil sie sein müssen

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:

  1. Viel Code-Duplizierung
  2. Eine Explosion in der Anzahl der Methodenargumente

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.

Scott Wisniewski
quelle
43

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 .

Joel Coehoorn
quelle
6
Einverstanden. In einem solchen Fall mache ich die Methode im Allgemeinen "privat statisch".
Harpo
6
Ich würde auch keine private statische Aufladung annehmen. Die Hauptsache ist, sich zu fragen: Passt diese Methode logischerweise als Teil dieses Typs oder ist sie nur aus Bequemlichkeitsgründen hier? Wenn letzteres der Fall ist, könnte es woanders besser passen?
Joel Coehoorn
1
Wie: "Könnte die neue Methode logischerweise woanders hingehören" - der Hinweis ist, dass sie nicht vom lokalen Status abhängt, vielleicht ist der Rückgabetyp dort, wo sie hingehört?
AndyM
20

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.

Michael
quelle
Ich denke, er bezieht sich hauptsächlich auf private Methoden
George Mauer
@ Ray - Richtig, dies gilt nur für nicht private Mitglieder. Ich habe meine Antwort aktualisiert, um dies widerzuspiegeln.
Michael
Meine Gedanken genau - nur weil Sie etwas statisch machen könnten , heißt das nicht, dass Sie müssen oder sollten .....
marc_s
Was würden Sie also für private Methoden tun, die statisch gemacht werden könnten?
Ray
@ Ray - Wahrscheinlich so lassen wie es ist, bis ich Grund genug habe, auf statisch umzusteigen.
Michael
13

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.

JP Alioto
quelle
11

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.

Jabe
quelle
7
Nicht unbedingt. Eine statische Methode greift nicht auf Instanzinformationen zu, keine Mitglieder, wie Sie sagten, kann jedoch mit anderen Klassen sowie einer anderen gängigen Methode interagieren. Statisch zu sein bedeutet nicht, dass die Kopplung notwendigerweise reduziert wird. Ich habe Ihren Standpunkt jedoch verstanden.
Victor Rodrigues
Stattdessen erhöht die statische Aktualität tatsächlich die Kopplung, da Sie auf genau diese statische Methode beschränkt sind und beispielsweise keine Möglichkeit haben, sie zu umgehen und somit das Verhalten nicht zu ändern .
HimBromBeere
8

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 ...

Jason Punyon
quelle
6

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.

Tamas Czinege
quelle
1
Eine statische Methode kann weiterhin Zugriff auf den Status haben. Es erhält nur den Status von dem Objekt, das an es übergeben wurde. Umgekehrt enthalten Instanzfelder nicht unbedingt einen veränderlichen Status.
Jørgen Fogh
6

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 .

Agnieszka
quelle
3
Das ist technisch wahr, aber nicht im eigentlichen materiellen Sinne. Der Unterschied zwischen statisch und nicht ist sehr, sehr selten ein Leistungsfaktor.
Foredecker
22
-1: Vorzeitige Optimierung des Lehrbuchs. Geschwindigkeit sollte sicherlich nicht das erste Kriterium bei der Entscheidung für statisch oder nicht statisch für den allgemeinen Fall sein.
Nicht sicher
2
Stimmen Sie mit Nicht sicher überein, dies sollte Ihr letzter Grund sein, jemals statisch gegen nicht zu betrachten.
Samuel
5
Mein Punkt ist, dass Geschwindigkeit einer der schlechtesten Gründe ist, warum Sie in 99% der Fälle entscheiden können, ob eine Funktion statisch oder nicht statisch ist. Es gibt weitaus wichtigere Überlegungen zum OO-Design, auf die andere Beiträge näher eingehen.
Nicht sicher
2
@agnieszka: Der besondere Grund für die generelle Verwendung von Instanzmethoden anstelle von statischen Methoden ist state. Wenn Sie Ihre Methoden statisch lassen, werden Sie in einer komplexen Anwendung Fehler einführen, die Sie dazu bringen, sich die Haare auszureißen. Denken Sie daran, den globalen Zustand, die Rennbedingungen, die Thread-Sicherheit usw. zu
ändern
5

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" ...

Thomas Hansen
quelle
4

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.

17 von 26
quelle
4

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.

Chris Shaffer
quelle
2

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".

Prankster
quelle
1
Sie können Ihre ReSharper-Einstellungen ändern: P
Bernhard Hofmann
1
Wenn es so einfach wäre, hätten wir keine Abnutzungserscheinungen vom Resharper ... jemals :)
Prankster
1

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.

Brian Ensink
quelle
Ja, aber wenn Sie dies eines Tages tun müssen, können Sie es immer nicht statisch machen. Oder fehlt mir etwas?
Ray
1
@ Ray - Ich beschreibe dies in meiner Antwort. statisch zu nicht statisch ist eine bahnbrechende Änderung, daher müssen alle Verbraucher modifiziert werden. Für ein kleines Programm keine große Sache, aber wenn es sich um eine Bibliothek handelt, die von anderen konsumiert werden kann, muss dies berücksichtigt werden.
Michael
Alle Aufrufstellen müssen von einem statischen Methodenaufruf in einen Mitgliedsfunktionsaufruf geändert werden.
Brian Ensink
Entschuldigung, das hast du nach meinem Kommentar hinzugefügt. In meinen Gedanken habe ich über private Methoden nachgedacht, aber das ist ein gültiger Punkt für öffentliche Methoden.
Ray
... oder eines Tages kannst du es rauswerfen. Diese Argumente sind nicht gut genug, um eine Methode nicht statisch zu machen.
Agnieszka
1

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.

Vordecker
quelle
1

Sie sollten über Ihre Methoden und Klassen nachdenken:

  • Wie wirst du sie benutzen?
  • Benötigen Sie viele Zugriffe von verschiedenen Ebenen Ihres Codes?
  • Ist dies eine Methode / Klasse, die ich in fast jedem denkbaren Projekt verwenden kann?

Wenn die letzten beiden "Ja" sind, sollte Ihre Methode / Klasse wahrscheinlich statisch sein.

Das am häufigsten verwendete Beispiel ist wahrscheinlich die MathKlasse. 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 ArrayKlasse. Es kehrt die Reihenfolge Ihres Arrays um.

Code:

public static void Reverse(Array array)

Es wird nicht einmal etwas zurückgegeben, Ihr Array ist umgekehrt, da alle Arrays Instanzen der Array-Klasse sind.

KdgDev
quelle
Die Mathematik ist ein schlechtes Beispiel. Ich denke, es ist besser: newnumber = number.round (2) als newnumber = Math.round (number)
graffic
3
Die Math-Klasse ist das perfekte Beispiel für die Verwendung statischer Klassen. Darum geht es in diesem Thema, nicht darum, wie Sie Zahlen runden
möchten
1

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:

Nachdem Sie die Methoden als statisch markiert haben, sendet der Compiler nicht virtuelle Aufrufseiten an diese Mitglieder. Durch das Ausgeben nicht virtueller Aufrufstandorte wird zur Laufzeit für jeden Aufruf eine Überprüfung verhindert, die sicherstellt, dass der aktuelle Objektzeiger nicht null ist. Dies kann zu einem messbaren Leistungsgewinn für leistungsabhängigen Code führen. In einigen Fällen stellt der Fehler beim Zugriff auf die aktuelle Objektinstanz ein Korrektheitsproblem dar.

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:

Obwohl diese Regel als Leistungsproblem eingestuft wird, beträgt die Leistungsverbesserung bei der statischen Erstellung einer Methode nur etwa 1%. Es handelt sich vielmehr um ein Korrektheitsproblem, das auf einen unvollständigen oder einen Fehler im Mitglied hinweisen kann, wenn andere Instanzmitglieder nicht verwendet werden. Eine Methode statisch (Markierung Gemeinsame in Visual Basic) macht es auf seine Absicht , nicht zu berühren Instanz Zustand zu löschen.

Scott Dorman
quelle
1

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 ...

Damageboy
quelle
1

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.

Lennaert
quelle
1

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.

IJ Kennedy
quelle
1
Was ist, wenn unterschiedliche Kunden von unterschiedlichen Niederlassungen bedient werden? Wenn Sie die Korrespondenz an die Hauptgeschäftsstelle der Bank senden, wird sie möglicherweise an die richtige Filiale weitergeleitet. Dies bedeutet jedoch nicht, dass ein Kunde nicht besser mit der Adresse der jeweiligen Filiale bedient werden kann, die ihn bedient.
Supercat
0

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
-1

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.

Jhonny D. Cano -Leftware-
quelle