Immer wenn ich lokale Variablen in einer Methode habe, schlägt ReSharper vor, sie in Konstanten zu konvertieren:
// instead of this:
var s = "some string";
var flags = BindingFlags.Public | BindingFlags.Instance;
// ReSharper suggest to use this:
const string s = "some string";
const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
Da dies wirklich konstante Werte (und keine Variablen) sind, verstehe ich, dass ReSharper vorschlägt, sie in const zu ändern.
Aber abgesehen davon gibt es einen anderen Vorteil bei der Verwendung von const (z. B. bessere Leistung), der die Verwendung const BindingFlags
anstelle des handlichen und lesbaren var
Schlüsselworts rechtfertigt ?
Übrigens: Ich habe hier gerade eine ähnliche Frage gefunden: Resharper schlägt mir immer vor, const string anstelle von string zu erstellen , aber ich denke, es geht mehr um Felder einer Klasse, in denen es um lokale Variablen / consts geht.
const
. Es gibt dem Compiler keine zusätzlichen Informationen. Überprüfen Sie diese Antwort für weitere Details.tl; dr für lokale Variablen mit Literalwerten
const
macht überhaupt keinen Unterschied.Ihre Unterscheidung von "Insider-Methoden" ist sehr wichtig. Schauen wir es uns an und vergleichen es dann mit
const
Feldern.Const lokale Variablen
Der einzige Vorteil einer
const
lokalen Variablen besteht darin, dass der Wert nicht neu zugewiesen werden kann.Allerdings
const
beschränkt sich auf primitive Typen (int
,double
, ...) undstring
, die ihre Anwendbarkeit begrenzt.Exkurs: Es gibt Vorschläge für den C # -Compiler, ein allgemeineres Konzept von "schreibgeschützten" Einheimischen ( hier ) zu ermöglichen, das diesen Vorteil auf andere Szenarien ausweiten würde. Sie werden wahrscheinlich nicht als gedacht werden
const
aber, und wahrscheinlich ein anderes Schlüsselwort für solche Erklärungen (dh haben würdenlet
oderreadonly var
oder so ähnlich).Betrachten Sie diese beiden Methoden:
private static string LocalVarString() { var s = "hello"; return s; } private static string LocalConstString() { const string s = "hello"; return s; }
Im eingebauten
Release
Modus sehen wir die folgende (gekürzte) IL:.method private hidebysig static string LocalVarString() cil managed { ldstr "hello" ret } .method private hidebysig static string LocalConstString() cil managed { ldstr "hello" ret }
Wie Sie sehen können, produzieren beide genau die gleiche IL. Ob das Lokal
s
istconst
oder nicht, hat keinen Einfluss.Gleiches gilt für primitive Typen. Hier ist ein Beispiel mit
int
:private static int LocalVarInt() { var i = 1234; return i; } private static int LocalConstInt() { const int i = 1234; return i; }
Und wieder die IL:
.method private hidebysig static int32 LocalVarInt() cil managed { ldc.i4 1234 ret } .method private hidebysig static int32 LocalConstInt() cil managed { ldc.i4 1234 ret }
Wir sehen also wieder keinen Unterschied. Hier kann es keinen Leistungs- oder Speicherunterschied geben. Der einzige Unterschied besteht darin, dass der Entwickler das Symbol nicht neu zuweisen kann.
Const-Felder
Der Vergleich eines
const
Feldes mit einem variablen Feld ist unterschiedlich. Ein nicht konstantes Feld muss zur Laufzeit gelesen werden. Am Ende haben Sie also IL wie folgt:// Load a const field ldc.i4 1234 // Load a non-const field ldsfld int32 MyProject.MyClass::_myInt
Es ist klar zu sehen, wie dies zu einem Leistungsunterschied führen kann, vorausgesetzt, die JIT kann selbst keinen konstanten Wert inline setzen.
Ein weiterer wichtiger Unterschied besteht in öffentlichen Konstantenfeldern, die von Assemblys gemeinsam genutzt werden. Wenn eine Assembly ein const-Feld verfügbar macht und eine andere es verwendet, wird der tatsächliche Wert dieses Felds zur Kompilierungszeit kopiert . Dies bedeutet, dass der alte (und möglicherweise falsche) Wert verwendet wird, wenn die Assembly, die das const-Feld enthält, aktualisiert wird, die using-Assembly jedoch nicht neu kompiliert wird.
Const-Ausdrücke
Betrachten Sie diese beiden Erklärungen:
const int i = 1 + 2; int i = 1 + 2;
Für das
const
Formular muss die Addition zur Kompilierungszeit berechnet werden, dh die Nummer 3 wird in der IL gespeichert.Für die Nichtform
const
kann der Compiler die Additionsoperation in der IL ausgeben, obwohl die JIT mit ziemlicher Sicherheit eine grundlegende Optimierung der konstanten Faltung anwenden würde, so dass der generierte Maschinencode identisch wäre.Der C # 7.3-Compiler gibt den
ldc.i4.3
Opcode für beide oben genannten Ausdrücke aus.quelle
Nach meinem Verständnis existieren Const-Werte zur Laufzeit nicht - dh in Form einer Variablen, die an einem bestimmten Speicherort gespeichert ist - sie werden zur Kompilierungszeit in MSIL-Code eingebettet. Und würde sich somit auf die Leistung auswirken. Mehr über die Laufzeit wäre nicht erforderlich, um auch eine Haushaltsführung (Konvertierungsprüfungen / Speicherbereinigung usw.) durchzuführen, sofern Variablen diese Überprüfungen erfordern.
quelle
const ist eine Kompilierungszeitkonstante - das heißt, Ihr gesamter Code, der die const-Variable verwendet, wird so kompiliert, dass er den konstanten Ausdruck enthält, den die const-Variable enthält. Die ausgegebene IL enthält diesen konstanten Wert selbst.
Dies bedeutet, dass der Speicherbedarf für Ihre Methode geringer ist, da für die Konstante zur Laufzeit kein Speicher zugewiesen werden muss.
quelle
const
Funktioniert nur mit Grundelementen (die dazu führen, dass IL Konstanten auf den Auswertungsstapel lädt, wie Sie sagen) und Zeichenfolgen (die dieselbe Speichermenge zuweisen, unabhängig davon, ob sie konstant sind oder nicht).Neben der geringen Leistungsverbesserung erzwingen Sie beim Deklarieren einer Konstante explizit zwei Regeln für sich selbst und andere Entwickler, die Ihren Code verwenden
Im Code dreht sich alles um Lesbarkeit und Kommunikation.
quelle
Ein const-Wert wird auch von allen Instanzen eines Objekts gemeinsam genutzt. Dies könnte auch zu einer geringeren Speichernutzung führen.
Als Beispiel:
public class NonStatic { int one = 1; int two = 2; int three = 3; int four = 4; int five = 5; int six = 6; int seven = 7; int eight = 8; int nine = 9; int ten = 10; } public class Static { static int one = 1; static int two = 2; static int three = 3; static int four = 4; static int five = 5; static int six = 6; static int seven = 7; static int eight = 8; static int nine = 9; static int ten = 10; }
Der Speicherverbrauch in .Net ist schwierig, und ich werde nicht vorgeben, die feineren Details zu verstehen. Wenn Sie jedoch eine Liste mit einer Million 'Static' instanziieren, wird wahrscheinlich erheblich weniger Speicher benötigt als wenn Sie dies nicht tun.
static void Main(string[] args) { var maxSize = 1000000; var items = new List<NonStatic>(); //var items = new List<Static>(); for (var i=0;i<maxSize;i++) { items.Add(new NonStatic()); //items.Add(new Static()); } Console.WriteLine(System.Diagnostics.Process.GetCurrentProcess().WorkingSet64); Console.Read(); }
Bei Verwendung von 'NonStatic' beträgt der Arbeitssatz 69.398.528 gegenüber nur 32.423.936 bei Verwendung von Static.
quelle
const
iststring
. Sowohl ein const string (const string s = "foo";
) als auch ein string literal (var s = "foo";
) werden interniert. Hier gibt es also keinen Unterschied zum Speicherverbrauch. Alle anderen konstanten Werte werden als Wert übergeben."hello"
interniert, sodass zwei Methoden, die"hello"
als lokale Variablen definiert werden, dieselbe Referenz verwenden (auf der Grundlage, dass Zeichenfolgen unveränderlich sind). Ist"hello".ToUpper()
jedoch ein Laufzeitwert, sodass mehrere Aufrufe mehrere Instanzen erzeugen.Das Schlüsselwort const teilt dem Compiler mit, dass es zur Kompilierungszeit vollständig ausgewertet werden kann. Dies hat einen Leistungs- und Speichervorteil, ist jedoch gering.
quelle
Konstanten in C # stellen einen benannten Speicherort im Speicher bereit , um einen Datenwert zu speichern. Dies bedeutet, dass der Wert der Variablen in der Kompilierungszeit bekannt ist und an einem einzigen Ort gespeichert wird.
Wenn Sie es deklarieren, ist es in der Microsoft Intermediate Language (MSIL) "fest codiert".
Obwohl ein wenig, kann es die Leistung Ihres Codes verbessern. Wenn ich eine Variable deklariere und sie zu einer Konstante machen kann, mache ich das immer. Nicht nur, weil es die Leistung verbessern kann, sondern auch, weil dies die Idee von Konstanten ist. Warum existieren sie sonst?
Reflektor kann in Situationen wie dieser sehr nützlich sein. Versuchen Sie, eine Variable zu deklarieren, und machen Sie sie dann zu einer Konstanten. Sehen Sie, welcher Code in IL generiert wird . Dann müssen Sie nur noch den Unterschied in den Anweisungen erkennen und sehen, was diese Anweisungen bedeuten.
quelle