Ein Teil der Namensfragen ist in C# keine Geschmacksfrage mehr. Die Framework Design Guidelines sind seit über zwanzig Jahren stabil, und die gesamte Klassenbibliothek folgt ihnen. Wer davon abweicht, erzeugt bei jedem Leser einen kurzen Moment der Irritation — und der summiert sich.
public class RechnungsService // PascalCase: Typen
{
private readonly IZahlungsGateway _gateway; // _camelCase: private Felder
private const int MaxVersuche = 3; // PascalCase: Konstanten
public decimal Gesamtbetrag { get; } // PascalCase: Eigenschaften
public void Verbuche(Rechnung rechnung) // PascalCase: Methoden
{ // camelCase: Parameter
var offenerBetrag = rechnung.Betrag; // camelCase: lokale Variablen
}
}
public interface IZahlungsGateway { } // I-Präfix: Schnittstellen
public enum Zahlungsart { Karte, Rechnung, Lastschrift } // Singular, Werte PascalCaseDas `I` ist die eine geduldete Ausnahme
Ungarische Notation — der Typ im Namen, wie strName oder iAnzahl — ist seit den 90ern abgeschafft; der Compiler kennt den Typ ohnehin. Das I bei Schnittstellen hat überlebt, weil es keine Typinformation trägt, sondern eine Rolle: Hier steht ein Vertrag, keine Implementierung.
Vier Konventionen, die im Alltag am meisten tragen
Async-Suffix bei Methoden, die einen Task liefern. Nicht Zierde, sondern Warnung: Wer LadeAsync() ohne await aufruft, sieht am Namen, dass er gerade etwas vergisst.
public async Task<Kunde> LadeKundeAsync(int id) { … }
var kunde = LadeKundeAsync(42); // liefert Task<Kunde> — der Name verrät den FehlerBooleans stellen eine Frage. IstAktiv, HatOffenePosten, KannStornieren — der Name liest sich an der Aufrufstelle wie ein Satz:
Aussage unklar
if (kunde.Aktiv) …
if (rechnung.Storno) …
if (!benutzer.Sperre) …Frage
if (kunde.IstAktiv) …
if (rechnung.WurdeStorniert) …
if (!benutzer.IstGesperrt) …Links könnte rechnung.Storno auch ein Objekt sein, das die Stornierung beschreibt. Rechts ist ausgeschlossen, dass es etwas anderes als ein bool ist.
Sammlungen im Plural, Einzelwerte im Singular. kunden ist eine Liste, kunde ist einer. Namen wie kundenListe tragen den Typ im Namen — dieselbe alte Krankheit wie strName. Und wenn aus der List<T> später ein IReadOnlyCollection<T> wird, ist der Name falsch, ohne dass es jemand merkt.
var, wenn der Typ rechts steht. Die Guidelines lassen hier Spielraum, die Praxis hat sich eingependelt:
var kunde = new Kunde(); // Typ steht rechts — var ist klar
var kunden = new List<Kunde>(); // dito
var betrag = rechnung.BerechneGesamtbetrag(); // grenzwertig: decimal? Money?
decimal betrag = rechnung.BerechneGesamtbetrag(); // besser, wenn der Typ zählt
int anzahl = 0; // explizit, wenn es auf den Typ ankommtDie Frage hinter `var`
Nicht «spare ich Tipparbeit», sondern: Verliert der Leser Information? Steht der Typ auf derselben Zeile, verliert er nichts. Kommt der Wert aus einem Methodenaufruf, dessen Rückgabetyp nicht offensichtlich ist, verliert er etwas.
Konventionen erzwingen statt diskutieren
Ab zwei Personen im Team ist jede Namensdiskussion im Review verlorene Zeit. Lege die Regeln in eine .editorconfig, dann meldet sie die IDE und der Build — und niemand muss sie mehr in einem Kommentar anmerken:
[*.cs]
# Private Felder: _camelCase, als Fehler statt als Vorschlag
dotnet_naming_rule.private_fields.severity = error
dotnet_naming_rule.private_fields.symbols = private_field
dotnet_naming_rule.private_fields.style = underscore_camel
dotnet_naming_symbols.private_field.applicable_kinds = field
dotnet_naming_symbols.private_field.applicable_accessibilities = private
dotnet_naming_style.underscore_camel.required_prefix = _
dotnet_naming_style.underscore_camel.capitalization = camel_caseKurz nachgedacht
Zählt nicht — nur zum Prüfen, ob es angekommen ist.
1.Warum hat das I-Präfix bei Schnittstellen die ungarische Notation überlebt?