Theoretisch sollte eine statische Methode etwas besser abschneiden als eine Instanzmethode, da alle anderen Dinge aufgrund des zusätzlichen versteckten this
Parameters gleich sind.
In der Praxis macht dies so wenig Unterschied, dass es im Rauschen verschiedener Compilerentscheidungen verborgen bleibt. (Daher könnten zwei Personen eine Person mit nicht übereinstimmenden Ergebnissen besser "beweisen" als die andere). Nicht zuletzt, weil das this
normalerweise in einem Register übergeben wird und sich oft in diesem Register befindet.
Dieser letzte Punkt bedeutet, dass wir theoretisch erwarten sollten, dass eine statische Methode, die ein Objekt als Parameter verwendet und etwas damit macht, etwas weniger gut ist als das Äquivalent als Instanz für dasselbe Objekt. Auch hier ist der Unterschied so gering, dass Sie, wenn Sie versuchen würden, ihn zu messen, wahrscheinlich eine andere Compilerentscheidung messen würden. (Zumal die Wahrscheinlichkeit, dass sich diese Referenz die ganze Zeit in einem Register befindet, auch ziemlich hoch ist).
Die tatsächlichen Leistungsunterschiede hängen davon ab, ob Sie Objekte künstlich im Speicher haben, um etwas zu tun, das natürlich statisch sein sollte, oder ob Sie Ketten der Objektübergabe auf komplizierte Weise verwickeln, um das zu tun, was natürlich Instanz sein sollte.
Daher für Nummer 1. Wenn es kein Problem ist, den Status beizubehalten, ist es immer besser, statisch zu sein, denn dafür ist statisch gedacht . Es ist kein Leistungsproblem, obwohl es eine allgemeine Regel gibt, mit Compiler-Optimierungen gut zu spielen - es ist wahrscheinlicher, dass sich jemand die Mühe gemacht hat, Fälle zu optimieren, die bei normaler Verwendung auftreten, als solche, die bei seltsamer Verwendung auftreten.
Nummer 2. Macht keinen Unterschied. Es gibt eine bestimmte Menge an Kosten pro Klasse für jedes Mitglied, die sowohl davon abhängt, wie viele Metadaten vorhanden sind, wie viel Code in der tatsächlichen DLL- oder EXE-Datei vorhanden ist, als auch davon, wie viel Jitted-Code vorhanden sein wird. Dies ist gleich, ob es sich um eine Instanz oder eine statische Instanz handelt.
Mit Punkt 3 this
ist wie this
. Beachten Sie jedoch:
Der this
Parameter wird in einem bestimmten Register übergeben. Wenn Sie eine Instanzmethode innerhalb derselben Klasse aufrufen, befindet sie sich wahrscheinlich bereits in diesem Register (es sei denn, sie wurde gespeichert und das Register aus irgendeinem Grund verwendet). Daher ist keine Aktion erforderlich, um das this
auf das zu setzen , worauf es eingestellt werden muss . Dies gilt bis zu einem gewissen Grad, z. B. wenn die ersten beiden Parameter der Methode die ersten beiden Parameter eines Aufrufs sind.
Da klar this
ist , dass dies nicht null ist, kann dies in einigen Fällen zur Optimierung von Anrufen verwendet werden.
Da klar this
ist , dass dies nicht null ist, kann dies dazu führen, dass inline-Methodenaufrufe wieder effizienter werden, da der Code, der zum Fälschen des Methodenaufrufs erstellt wird, einige ohnehin erforderliche Nullprüfungen weglassen kann.
Das heißt, Nullschecks sind billig!
Es ist erwähnenswert, dass generische statische Methoden, die auf ein Objekt und nicht auf Instanzmethoden einwirken, einen Teil der unter http://joeduffyblog.com/2011/10/23/on-generics-and-some-of- diskutierten Kosten reduzieren können. die zugehörigen Gemeinkosten / in dem Fall, in dem die angegebene Statik für einen bestimmten Typ nicht aufgerufen wird. Wie er es ausdrückt "Nebenbei bemerkt, es stellt sich heraus, dass Erweiterungsmethoden eine großartige Möglichkeit sind, generische Abstraktionen mehr für das Spiel zu bezahlen."
Beachten Sie jedoch, dass dies nur die Instanziierung anderer von der Methode verwendeter Typen betrifft, die ansonsten nicht vorhanden sind. Als solches trifft es wirklich nicht auf viele Fälle zu (eine andere Instanzmethode verwendete diesen Typ, ein anderer Code irgendwo anders verwendete diesen Typ).
Zusammenfassung:
- Meistens sind die Leistungskosten der Instanz gegenüber der statischen unter vernachlässigbar.
- Welche Kosten dort anfallen, wird in der Regel dort anfallen, wo Sie beispielsweise statische Aufladung missbrauchen oder umgekehrt. Wenn Sie es nicht zu einem Teil Ihrer Entscheidung zwischen statisch und Instanz machen, erhalten Sie mit größerer Wahrscheinlichkeit das richtige Ergebnis.
- Es gibt seltene Fälle, in denen statische generische Methoden in einem anderen Typ dazu führen, dass weniger Typen erstellt werden als generische Instanzmethoden, was dazu führen kann, dass es manchmal einen kleinen Vorteil hat, selten verwendet zu werden (und "selten" bezieht sich darauf, mit welchen Typen es in der verwendet wird Lebensdauer der Anwendung, nicht wie oft sie aufgerufen wird). Sobald Sie wissen, wovon er in diesem Artikel spricht, werden Sie feststellen, dass es für die meisten Entscheidungen zwischen statischen und instanziellen Instanzen ohnehin zu 100% irrelevant ist. Bearbeiten: Und es hat meistens nur diese Kosten mit ngen, nicht mit jitted Code.
Bearbeiten: Ein Hinweis darauf, wie billig Null-Checks sind (was ich oben behauptet habe). Die meisten Nullprüfungen in .NET prüfen überhaupt nicht auf Null, sondern setzen ihre Arbeit mit der Annahme fort, dass sie funktionieren wird. Wenn eine Zugriffsausnahme auftritt, wird sie zu einer NullReferenceException
. Wenn der C # -Code konzeptionell eine Nullprüfung beinhaltet, weil er auf ein Instanzmitglied zugreift, sind die Kosten, wenn er erfolgreich ist, tatsächlich Null. Eine Ausnahme wären einige Inline-Aufrufe (weil sie sich so verhalten möchten, als hätten sie ein Instanzmitglied angerufen), und sie treffen nur ein Feld, um dasselbe Verhalten auszulösen. Daher sind sie auch sehr billig und können trotzdem oft weggelassen werden (zB wenn der erste Schritt in der Methode den Zugriff auf ein Feld wie es war).