{"id":18390640,"url":"https://github.com/aspnetde/csharp-coding-guidelines","last_synced_at":"2025-04-12T07:58:52.567Z","repository":{"id":21379172,"uuid":"24696699","full_name":"aspnetde/CSharp-Coding-Guidelines","owner":"aspnetde","description":null,"archived":false,"fork":false,"pushed_at":"2016-01-03T21:49:31.000Z","size":10,"stargazers_count":3,"open_issues_count":0,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-12T07:58:46.673Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aspnetde.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-10-01T21:48:34.000Z","updated_at":"2017-12-04T09:05:47.000Z","dependencies_parsed_at":"2022-07-30T04:07:51.545Z","dependency_job_id":null,"html_url":"https://github.com/aspnetde/CSharp-Coding-Guidelines","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aspnetde%2FCSharp-Coding-Guidelines","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aspnetde%2FCSharp-Coding-Guidelines/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aspnetde%2FCSharp-Coding-Guidelines/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aspnetde%2FCSharp-Coding-Guidelines/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aspnetde","download_url":"https://codeload.github.com/aspnetde/CSharp-Coding-Guidelines/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248537101,"owners_count":21120701,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T01:48:41.094Z","updated_at":"2025-04-12T07:58:52.547Z","avatar_url":"https://github.com/aspnetde.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# C# Coding Style Guidelines\n\nDie hier dargestellten Regeln und Empfehlungen sind nicht \"die Wahrheit\", sondern Ergebnis jahrelanger Arbeit und Erfahrung in der Entwicklung mit C# und entsprechend Grundlage aller [meiner](https://thomasbandt.com/) aktuellen C#-Projekte und derer meiner Firma [69°](http://www.69grad.de/).\n\n## Übersicht\n\n- [Namenskonventionen](#Namenskonventionen)  \n- [Struktur von Klassen (und Strukturen)](#Struktur)  \n- [Groß- und Kleinschreibung](#Stil)  \n- [PascalCase \u0026 camelCase](#PascalCaseCamelCase)\n- [Ungarische Notation](#UngarischeNotation)\n- [Konstanten](#Konstanten)\n- [Namespaces](#Namespaces)\n- [Geschweifte Klammern](#GeschweifteKlammern)\n- [Leerzeichen](#Leerzeichen)\n- [Verwendung von var](#Var)\n- [Verzicht auf this](#This)\n- [Verwendung des \"private\"-Modifizierers](#Private)\n- [Leerzeilen](#Leerzeilen)\n- [Lines of Code (LOC) in Klassen und Methoden](#LOC)\n- [Kommentare](#Kommentare)\n\n\u003ca name=\"Namenskonventionen\"/\u003e\n## Namenskonventionen\n\n### Sprechende Namen\n\nAlle Namen müssen treffend benannt werden, sodass leicht verständlich ist, wofür sie stehen.\n\nNicht gut (Wofür wird dieser StringBuilder eingesetzt?)\n\n```cs\nvar stringBuilder = new StringBuilder();\n```\n\nBesser! Jetzt ist klar, was damit gemacht wird.\n\n```cs\nvar htmlOutput = StringBuilder();\n```\n\n### Aussprechbare Namen\n\nEine Variable, die einen Kontext repräsentiert, kann ruhig `context` heißen, aber bitte nicht `cxt` oder gar `c`. Solche Abkürzungen sind schwer zu lesen und erschweren so das Verstehen von Code.\n\n### Vermeidung von \"Weasel Words\"\n\nBezeichnungen wie `Manager`, `Processor`, `Service` o.ä. sind zu vermeiden, auch in Zusammensetzungen. Denn aus ihnen geht nicht hervor, was sie tun.\n\nStattdessen sollten sinnvolle, für sich sprechende Bezeichnungen der jeweiligen Klassen verwendet werden.\n\nAusnahmen bestätigen die Regel: dort, wo es sich um handelsübliche Bezeichnungen oder vom Framework vorgegebene Konventionen handelt, können Ausnahmen gemacht werden.\n\nSo ist ein `Repository` eine Menge, man könnte also statt `StoryRepository` schlicht auch `Stories` verwenden. Da dies jedoch potentiell schnell zu Missverständnissen mit Objekten in anderen Bereichen der Anwendung außerhalb des Datenzugriffs führt, kann `Repository` genutzt werden. Erst Recht, wenn die Aufteilung in `StoryReadRepository` und `StoryWriteRepository` erfolgt.\n\nÄhnliches gilt bei ASP.NET MVC bspw. für Controller. Hier ist es schlicht Konvetion, den `StoryController` zu verwenden.\n\n\u003ca name=\"Struktur\"/\u003e\n## Struktur von Klassen (und Strukturen)\n\nGrundsätzlich sollten sich Klassen und Strukturen flüssig von oben nach unten lesen lassen, wobei eine darüber hinausgehende inhaltliche Strukturierung sinnvoll ist:\n\n1. Konstanten\n2. Private Felder\n3. Öffentliche Eigenschaften (Properties)\n4. Konstruktor(en)\n5. Öffentliche Methoden\n6. Private Methoden\n\nBeispiel:\n\n```cs\npublic class Foo\n{\n    private const int BAR = 1;\n    \n    private readonly string _fooBar;\n    \n    public string Whatever { get; set; }\n    \n    public Foo()\n    {\n        _fooBar = \"barFoo\";\n    }\n    \n    public void MachWas()\n    {\n        Was();\n    }\n    \n    private void Was()\n    {\n    }\n}\n```\n\n\u003ca name=\"Stil\"/\u003e\n## Groß- und Kleinschreibung\n\nGrundsätzlich gilt: Namespaces, Klassen und Properties werden immer groß geschrieben.\n\n**Falsch:**\n\n```cs\nnamespace whatstays\n{\n\tpublic class story\n\t{\n\t\tpublic string title { get; set; }\n\t}\n}\n```\n\n**Richtig:**\n\n```cs\nnamespace Whatstays\n{\n\tpublic class Story\n\t{\n\t\tpublic string Title { get; set; }\n\t}\n}\n```\n\nParameter oder (methoden-interne) Variablennamen werden klein geschrieben.\n\n**Falsch:**\n\n```cs\npublic void Foo(string Bar)\n{\n\tstring FirstName = Bar;\n}\n```\n\n**Richtig:**\n\n```cs\npublic void Foo(string bar)\n{\n\tstring firstName = bar;\n}\n```\n\n\u003ca name=\"PascalCaseCamelCase\"/\u003e\n## PascalCase \u0026 camelCase\n\nWerden Bezeichnungen aus mehreren Wörtern zusammengesetzt, so erfolgt dies per `CamelCase` (Anfangsbuchstabe klein, gilt für Parameter oder (methoden-interne) Variablennamen) bzw. `PascalCase (mit großem Anfangsbuchstaben, gilt für Namespaces, Klassen und Properties).\n\n**Falsch:**\n\n```cs\npublic class Story_Repository\n{\n\tpublic IEnumerable\u003cStory\u003e find_by_Name(string story_name)\n\t{\n\t\t// ...\n\t}\n}\n```\n\n**Richtig:**\n\n```cs\npublic class StoryRepository\n{\n\tpublic IEnumerable\u003cStory\u003e FindByName(string storyName)\n\t{\n\t\t// ...\n\t}\n}\n```\n\n### Sonderfall: Konstanten\n\nSiehe: [Konstanten](#Konstanten).\n\n### Sonderfall: Private Felder\n\nPrivate Felder beginnen **grundsätzlich** mit einem Unterstrich, sodass diese leicht von Parametern und lokalen Variablen unterschieden werden können.\n\n**Falsch:**\n\n```cs\npublic class Foo\n{\n    private int bar;\n    \n    public Foo(int bar)\n    {\n        this.bar = bar;\n    }\n}\n```\n\n**Richtig:**\n\n```cs\npublic class Foo\n{\n    private int _bar;\n    \n    public Foo(int bar)\n    {\n        _bar = bar;\n    }\n}\n```\n\n### Sonderfall: Tests\n\nUm die Lesbarkeit von automatisierten Tests sowohl im TestRunner als auch im konkreten Test-Code zu erhöhen, setzen wir hier ausnahmslos auf Unterstriche zur Trennung von Wörtern.\n\n**Falsch:**\n\n```cs\n[TestFixture]\npublic class WennDieSonneScheint\n{\n\t[Test]\n\tpublic void WächstInMeinemGartenGras()\n\t{\n\t\t// ...\n\t}\n}\n```\n\n**Richtig:**\n\n```cs\n[TestFixture]\npublic class Wenn_die_Sonne_scheint\n{\n\t[Test]\n\tpublic void Wächst_in_meinem_Garten_Gras()\n\t{\n\t\t// ...\n\t}\n}\n```\n\n_Anmerkung: an dieser Stelle sind ausnahmsweise auch Umlaute und andere Sonderzeichen der Sprache erlaubt, in der der Test formuliert wird. Der Grund hierfür ist einfach: Tests sind häufig eher Spezifikationen, und diese lassen sich flüssiger erstellen und schreiben, wenn man auf die Formatierung nicht sonderlich viel Rücksicht nehmen muss. Siehe auch http://code.69grad.de/69-testing._ \n\n\u003ca name=\"UngarischeNotation\"/\u003e\n## Ungarische Notation\n\nBei der ungarischen Notation wird dem Variablennamen der Typ vorangestellt, was bei untypisierten Sprachen unter seltenen Umständen hilfreich sein kann, bei C# jedoch vollkommen nutzlos ist.\n\nEin Beispiel wäre\n\n```cs\nstrName = \"Max Mustermann\";\nintAlter = 69;\n```\n\n**Ungarische Notation wird nicht verwendet** — *never, ever*.\n\n\u003ca name=\"Konstanten\"/\u003e\n## Konstanten\n\nKonstanten werden in der Regel durchgängig Groß und mit Unterstrichen geschrieben. Dies soll ihre herausgehobene Stellung betonen und das Verständnis entsprechend fördern.\n\nBeispiel:\n\n```cs\npublic class Auto\n{\n    private const double MINIMALER_REIFENDRUCK = 2;\n    private const double MAXIMALER_REIFENDRUCK = 3;\n}\n```\n\n\u003ca name=\"Namespaces\"/\u003e\n## Namespaces\n\nFür Namespaces gilt: so kurz wie möglich, so lang wie nötig.\n\nDer Aufbau erfolgt nach folgendem Prinzip:\n\n\t{Kunde}.{Projekt}.{Logischer Bereich}.{…}\n\nRichtig wäre:\n\n\tWhatstays.Website.Controllers\n\nFalsch wären:\n\n\tWhatstaysWebsiteControllers\n\tWhatstays_Website.Controllers\n\n\u003ca name=\"GeschweifteKlammern\"/\u003e\n## Geschweifte Klammern\n\nGeschweifte Klammern, die einen Block definieren, werden in einer eigenen Zeile geöffnet und in einer eigenen Zeile wieder geschlossen. Richtig ist also:\n\n```cs\npublic void Foo()\n{\n}\n```\n\nFalsch hingegen ist:\n\n```cs\npublic void Bar() {\n}\n```\n\n\u003ca name=\"Leerzeichen\"/\u003e\n## Leerzeichen\n\nNach Methodennamen sowie nach öffnenden und vor schließenden Klammern werden keine Leerzeichen gesetzt.\n\n**Falsch**\n\n```cs\npublic void Foo ( string param )\n{\n}\n```\n\n**Richtig**\n\n```cs\npublic void Foo(string param)\n{\n}\n```\n\n\u003ca name=\"Var\"/\u003e\n## Verwendung von var\n\n`var` verwenden wir in der Regel dort, wo der Typ einer Variablen bei deren Zuweisung klar ersichtlich wird:\n\n```cs\nvar duck = new Duck();\n```\n\nHäufig ist das deutlich lesbarer als die doch ziemlich redundante Deklaration mit explizitem Typ:\n\n```cs\nDuck duck = new Duck();\n```\n\nBei primitiven Datentypen wie `int` und `double`, die Zahlen repräsentieren, ziehen wir hingegen den expliziten Typ vor. So ist leichter zu erkennen, ob es sich um Fließkomma- oder ganze Zahlen handelt.\n\n\u003ca name=\"This\"/\u003e\n## Verzicht auf this\n\nAuf die Verwendung von this wird vollständig verzichtet. Durch die Verwendung des Unterstrich `_` für private Felder gibt es hierzu auch keinen Zwang mehr.\n\n\u003ca name=\"Private\"/\u003e\n## Verwendung des \"private\"-Modifizierers\n\nObwohl auf ihn ebenso verzichtet werden könnte, da alles ohne Modifizierer per default `private` ist, verwenden wir ihn für alle privaten Elemente. Grund ist der schnellere Überblick über öffentliche und nicht-öffentliche Elemente beim Einlesen in neuen Code, wenn die nicht-öffentlichen auch direkt als solche explizit gekennzeichnet sind.\n\n\u003ca name=\"Leerzeilen\"/\u003e\n## Leerzeilen\n\nNach öffnenden und vor schließenden Klammern werden keine Leerzeilen eingefügt.\n\n**Falsch:**\n\n```cs\npublic class Foo\n{\n\n    private int _bar;\n    \n    public Foo(int bar)\n    {\n\n        _bar = bar;\n\n    }\n\n}\n```\n\n**Richtig:**\n\n```cs\npublic class Foo\n{\n    private int _bar;\n    \n    public Foo(int bar)\n    {\n        _bar = bar;\n    }\n}\n```\n\nInnerhalb von Methoden werden Leerzeilen möglichst so eingesetzt, dass einzelne Funktionsblöcke innerhalb einer Methode separiert werden.\n\nSo würde z.B. Folgendes (bezogen auf die Formatierung) Sinn machen:\n\n```cs\npublic class Foo\n{\n\tprivate int _bar;\n\n\tpublic int Foo(int bar)\n\t{\n\t\tint foo = bar * 2;\n\t\t_bar = foo;\n\t\t\t\t\t\n\t\treturn foo;\n\t}\n}\n```\n\n\u003ca name=\"LOC\"/\u003e\n## Lines of Code (LOC) in Klassen und Methoden\n\nAusnahmen bestätigen die Regel, die besagt: eine Klasse mit mehr als ca. 150 Zeilen Code ist schwieriger zu verstehen, als eine Klasse mit weniger Zeilen.\n\nNicht immer ist das einzuhalten, häufig aber macht das Aufteilen in mehrere Klassen durchaus Sinn (Single Responsibility Principle).\n\nLaut \"Clean Code\" sollte eine Methode nicht mehr als 8 Zeilen Code enthalten. Das ist in der Praxis kaum möglich. Jedoch lässt sich wohl auch hier darauf achten, dass die prozedurale Abarbeitung \"einer\" Aufgabe in einer großen Methode häufig in viele kleine Methoden aufgebrochen werden kann.\n\n\u003ca name=\"Kommentare\"/\u003e\n## Kommentare\n\nWir versuchen den Code grundsätzlich so zu schreiben, dass er sowohl von der Benennung der Objekte als auch von der konkreten Implementierung her leicht lesbar und damit verständlich ist.\n\nDeshalb ist es häufig nicht sinnvoll, Code intensiv zu dokumentieren, da er für sich selbst sprechen sollte.\n\nErscheint beispielsweise die Implementierung einer Methode derart komplex, dass Kommentare sinnvoll werden, sollte zunächst geprüft werden, ob die Methode nicht besser in mehrere kleine Methoden aufgebrochen werden kann.\n\nIst dies nicht möglich oder erscheinen Kommentare dennoch sinnvoll, dann eigenen sich XML-Kommentare in C# am besten. Das gilt im Übrigen natürlich auch für Komponenten oder Libaries, die häufig von Dritten eingesetzt werden. Hier dienen XML-Kommentare innerhalb der üblichen Entwicklungsumgebungen als Quelle für die Hilfe-Texte, die die IntelliSense-Funktionen zur Verfügung stellen.\n\n```cs\n/// \u003csummary\u003e\n/// Bar!\n/// \u003c/summary\u003e\npublic class Foo\n{\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faspnetde%2Fcsharp-coding-guidelines","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faspnetde%2Fcsharp-coding-guidelines","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faspnetde%2Fcsharp-coding-guidelines/lists"}