Menu

C# Variablen: var, const, readonly, Gültigkeitsbereich und Benennung

Wie du in C# Variablen deklarierst und zuweist, wann var eine gute Idee ist und wann nicht, wie der Gültigkeitsbereich funktioniert, der Unterschied zwischen const, readonly und static readonly, Namenskonventionen und der Fehler bei nicht zugewiesenen Variablen.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

Eine Variable ist ein benannter Speicherort mit einem festen Typ. In C# deklarierst du sie mit einem Typ und einem Namen und gibst ihr optional in derselben Anweisung einen Wert. Der Typ ändert sich danach nie: Eine int-Variable enthält Ganzzahlen, solange sie existiert.

Ausgabe:

Priya bought 5 items for 20.25
10

Einen Wert des falschen Typs zuzuweisen ist ein Kompilierfehler: quantity = "five"; scheitert mit CS0029 (cannot implicitly convert type 'string' to 'int'). Umwandlungen zwischen Typen sind explizit; siehe Typumwandlung.

var: den Compiler den Typ ableiten lassen

var deklariert eine lokale Variable, deren Typ aus ihrem Initialisierer abgeleitet wird. Das ist keine dynamische Typisierung: Der Typ steht zur Kompilierzeit fest, genau so, als hättest du ihn ausgeschrieben.

Ausgabe:

String
Int32
Decimal
Double
List`1

Für var gelten drei Regeln. Es funktioniert nur für lokale Variablen (nicht für Felder oder Parameter). Die Variable muss in der Deklaration initialisiert werden: var x; ist Fehler CS0818, „Implicitly-typed variables must be initialized“. Und der Initialisierer muss einen Typ haben: var nothing = null; kompiliert nicht, weil null allein keinen Typ hat.

Wann du es verwendest, ist eine Frage des Teamstils. Die übliche Richtlinie: var verwenden, wenn der Typ aus der rechten Seite offensichtlich ist, und den Typ ausschreiben, wenn nicht:

var orders = new List<Order>();         // obvious: var is fine
var reader = new StreamReader(path);    // obvious
decimal discount = CalculateDiscount(); // not obvious: name the type
int count = items.Count();              // makes the intent clear

Eine subtile Falle: var total = 0; macht total zu einem int, sodass späteres Addieren von 2.5 scheitert, und var price = 10; ist ein int, kein decimal. Wenn der Typ des Literals nicht der gewünschte ist, schreibe den Typ aus oder hänge ein Suffix an (10m, 0.0).

Gültigkeitsbereich

Eine lokale Variable existiert von ihrer Deklaration bis zum Ende des Blocks { }, in dem sie deklariert wurde. Variablen aus einem Schleifenkopf oder einem if-Rumpf sind danach nicht sichtbar.

Ausgabe:

high
240

Anders als C und C++ erlaubt C# nicht, dass ein innerer Block eine lokale Variable mit demselben Namen wie eine im umgebenden Block deklariert (Fehler CS0136): Ein Name muss in der ganzen Methode dasselbe bedeuten. Zwei nebeneinanderliegende Blöcke dürfen einen Namen wiederverwenden, wie es zwei separate for-Schleifen tun, die jeweils i deklarieren.

Definitive Zuweisung

Lokale Variablen haben keinen Standardwert. Der Compiler verfolgt jeden Pfad durch die Methode und verweigert das Kompilieren, wenn eine Variable gelesen werden könnte, bevor sie zugewiesen wurde:

int discount;
if (isMember)
{
    discount = 10;
}
Console.WriteLine(discount);
// error CS0165: Use of unassigned local variable 'discount'

Behebe das, indem du bei der Deklaration initialisierst (int discount = 0;) oder in jedem Zweig zuweist (ergänze ein else). Felder und Array-Elemente sind anders: Sie werden automatisch auf den Standardwert ihres Typs gesetzt (0, false, null).

const: Konstanten zur Kompilierzeit

Ein const ist ein zur Kompilierzeit festgelegter Wert. Er muss mit einem konstanten Ausdruck initialisiert werden (einem Literal, einer anderen Konstante oder Arithmetik darauf) und kann nur eine Zahl, ein char, bool, string, Enum oder null sein.

Ausgabe:

Price in EUR
120.00 EUR
350

Ein const-Feld ist implizit static, der Zugriff läuft also über den Typnamen (Pricing.VatRate), und static const zu schreiben ist ein Fehler. Der Compiler kopiert den Wert an jede Stelle, die ihn verwendet. Deshalb kosten Konstanten zur Laufzeit nichts, und deshalb sollte eine öffentliche Konstante in einer Bibliothek ein Wert sein, der sich nie ändert (wie die Anzahl der Tage einer Woche).

readonly und static readonly

Ein readonly-Feld kann nur in seiner Deklaration oder in einem Konstruktor seiner Klasse zugewiesen werden. Nach der Konstruktion kann es sich nicht mehr ändern. Anders als bei const wird sein Wert zur Laufzeit berechnet, kann jeden Typ haben und sich zwischen Objekten unterscheiden.

Ausgabe:

ACC-17 opened 2024-05-02
Launch: 2020-01-15
basic, pro

Die letzten Zeilen zeigen das häufige Missverständnis: readonly schützt das Feld, nicht das Objekt, auf das es zeigt. Plans verweist immer auf dasselbe Array, aber die Elemente des Arrays können sich trotzdem ändern. Für wirklich unveränderliche Collections nimm ReadOnlyCollection<T> oder ImmutableArray<T>.

Die drei im Überblick:

constreadonlystatic readonly
Wert bekanntZur KompilierzeitZur LaufzeitZur Laufzeit
Erlaubte TypenZahlen, char, bool, string, Enums, nullAlleAlle
Gesetzt inNur in der DeklarationDeklaration oder KonstruktorDeklaration oder statischer Konstruktor
Pro Objekt oder gemeinsamGemeinsam (implizit statisch)Pro ObjektGemeinsam
Lokale VariablenJa (const int x = 1;)NeinNein

Namenskonventionen

C#-Namen unterscheiden Groß- und Kleinschreibung (total und Total sind verschiedene Variablen) und müssen mit einem Buchstaben oder Unterstrich beginnen. Die Konventionen von Microsoft, an die sich fast jeder C#-Code hält:

  • Lokale Variablen und Parameter: camelCase (orderCount, unitPrice).
  • Konstanten, Properties, Methoden, Klassen und öffentliche Felder: PascalCase (MaxItems, VatRate).
  • Private Felder: _camelCase mit führendem Unterstrich (_balance), eine in .NET-Code weit verbreitete Konvention.
  • Booleans lesen sich wie Fragen: isActive, hasDiscount, canRetry.
  • Vermeide Abkürzungen und ungarische Präfixe (strName, iCount).

Ein C#-Schlüsselwort kann kein Name sein, außer du stellst ein @ voran: var @class = "5B"; ist erlaubt, was gelegentlich für generierten Code oder JSON-Feldnamen nützlich ist.

Tauschen und Mehrfachzuweisung

Seit C# 7 kannst du mit Tupeln mehrere Variablen in einer Anweisung zuweisen, was einen einzeiligen Tausch ergibt:

Ausgabe:

20 10
Lisbon: 545,000

Die zweite Form ist Dekonstruktion: Sie deklariert aus einem Tupel city als string und population als int. Mehr unter Tupel.

Häufig gestellte Fragen

Was ist var in C#?

var weist den Compiler an, den Typ einer lokalen Variable aus dem Wert abzuleiten, mit dem sie initialisiert wird: var count = 5; deklariert ein int. Die Variable ist trotzdem statisch typisiert und kann später keinen String aufnehmen. var funktioniert nur für lokale Variablen, die in derselben Anweisung initialisiert werden.

Was ist der Unterschied zwischen const und readonly in C#?

Ein const ist eine Konstante zur Kompilierzeit: Ihr Wert muss beim Kompilieren bekannt sein (Zahlen, Strings, bool, null), sie ist implizit statisch, und der Wert wird an jede Stelle kopiert, die ihn verwendet. Ein readonly-Feld wird einmal zur Laufzeit gesetzt, in seiner Deklaration oder in einem Konstruktor, kann jeden Typ haben und sich pro Objekt unterscheiden.

Wann sollte ich static readonly statt const verwenden?

Nimm static readonly für einen gemeinsamen Wert, der keine Konstante zur Kompilierzeit sein kann, etwa ein DateTime, ein Array oder ein Objekt, oder für einen öffentlichen Wert, der sich zwischen Versionen einer Bibliothek ändern könnte. Weil const-Werte in aufrufende Assemblies kopiert werden, muss nach der Änderung einer öffentlichen Konstante jede Assembly neu kompiliert werden, die sie nutzt.

Was bedeutet „use of unassigned local variable“ in C#?

Fehler CS0165: Der Compiler hat einen Pfad gefunden, auf dem eine lokale Variable gelesen wird, bevor ihr ein Wert zugewiesen wurde. Lokale Variablen haben in C# keinen Standardwert. Initialisiere die Variable bei der Deklaration oder sorge dafür, dass jeder Zweig des if/switch ihr vor der Verwendung einen Wert zuweist.

Soll ich in C# var oder explizite Typen verwenden?

Beides ist in Ordnung; Teams legen einen Stil fest. Eine verbreitete Regel: var verwenden, wenn der Typ aus der rechten Seite offensichtlich ist (var list = new List<string>();), und den Typ ausschreiben, wenn nicht (decimal total = GetTotal();). Die Codebasis der .NET-Runtime folgt ungefähr dieser Regel.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S