Gängige C#-Codierungskonventionen

Ein Codestandard ist für die Aufrechterhaltung der Codelesbarkeit sowie für Konsistenz und Zusammenarbeit innerhalb eines Entwicklungsteams unerlässlich. Code, der Branchenpraktiken und etablierten Richtlinien folgt, ist einfacher zu verstehen, zu verwalten und zu erweitern. Die meisten Projekte erzwingen eine konsistente Formatvorlage durch Codekonventionen. Die Projekte dotnet/docs und dotnet/samples sind da keine Ausnahme. In dieser Artikelreihe lernen Sie unsere Codierungskonventionen und die Tools kennen, die wir verwenden, um sie zu erzwingen. Sie können unsere Konventionen entsprechend den Anforderungen Ihres Teams anpassen oder ändern.

Wir haben unsere Konventionen basierend auf den folgenden Zielen gewählt:

  1. Korrektheit: Unsere Beispiele werden in Ihre Anwendungen kopiert und eingefügt. Wir erwarten, dass wir also Code erstellen müssen, der auch nach mehreren Bearbeitungen robust und korrekt ist.
  2. Lehren: Der Zweck unserer Beispiele ist es, .NET und C# zu vermitteln. Aus diesem Grund legen wir keine Einschränkungen für Sprachfeatures oder APIs fest. Stattdessen zeigen diese Beispiele, wann ein Feature eine gute Wahl ist.
  3. Konsistenz: Leser erwarten eine konsistente Erfahrung in unseren Inhalten. Alle Beispiele sollten demselben Stil entsprechen.
  4. Einführung: Wir aktualisieren unsere Beispiele aggressiv, um neue Sprachfeatures zu verwenden. Diese Praxis erhöht das Bewusstsein für neue Features und macht sie allen C#-Entwicklern vertrauter.

Wichtig

Die Richtlinien werden von Microsoft verwendet, um Beispiele und die Dokumentation zu entwickeln. Sie wurden aus dem Leitfaden .NET Runtime, C#-Codierungsstil und C#-Compiler (roslyn) übernommen. Wir haben diese Richtlinien ausgewählt, da sie über mehrere Jahre der Open Source-Entwicklung getestet wurden. Sie haben Communitymitgliedern geholfen, an den Laufzeit- und Compilerprojekten teilzunehmen. Sie sind ein Beispiel für gängige C#-Konventionen und keine verbindliche Liste (diese finden Sie in den Framework-Entwurfsrichtlinien).

Die Ziele Lehren und Einführung sind der Grund dafür, dass sich die Docs-Codierungskonvention von den Laufzeit- und Compilerkonventionen unterscheidet. Sowohl die Laufzeit als auch der Compiler verfügen über strenge Leistungsmetriken für langsamste Pfade. Bei vielen anderen Anwendungen ist das nicht der Fall. Unser Ziel Lehren erfordert, dass wir kein Konstrukt verbieten. Stattdessen zeigen Beispiele, wann Konstrukte verwendet werden sollen. Wir aktualisieren Beispiele aggressiver als die meisten Produktionsanwendungen. Unser Ziel Einführung erfordert, dass wir Code zeigen, den Sie heute schreiben sollten, auch wenn im letzten Jahr geschriebener Code keine Änderungen benötigt.

In diesem Artikel werden unsere Richtlinien erläutert. Die Richtlinien wurden im Laufe der Zeit weiterentwickelt, und Sie finden Beispiele, die nicht unseren Richtlinien entsprechen. Wir freuen uns über PRs, die diese Beispiele konform machen, oder über Probleme, die uns auf Proben aufmerksam machen, die wir aktualisieren sollten. Unsere Richtlinien sind Open Source und wir freuen uns immer über PRs und Probleme. Wenn Ihr Beitrag diese Empfehlungen jedoch ändern würde, sollten Sie das Thema jedoch zunächst zur Diskussion stellen. Sie können unsere Richtlinien gerne verwenden oder sie an Ihre Bedürfnisse anpassen.

Analysetools und andere Tools

Tools können Ihrem Team dabei helfen, Ihre Standards zu erzwingen. Sie können die Codeanalyse aktivieren, um die gewünschten Regeln zu erzwingen. Sie können auch eine editorconfig erstellen, sodass Visual Studio Ihre Stilrichtlinien automatisch erzwingt. Als Ausgangspunkt können Sie die Datei des dotnet/docs-Repositorys kopieren, um unsere Formatvorlage zu verwenden.

Diese Tools erleichtern es Ihrem Team, Ihre bevorzugten Richtlinien zu übernehmen. Visual Studio wendet die Regeln in allen .editorconfig-Dateien im Bereich an, um Ihren Code zu formatieren. Sie können mehrere Konfigurationen verwenden, um unternehmensweite Standards, Teamstandards und sogar präzise Projektstandards zu erzwingen.

Die Codeanalyse erzeugt Warnungen und Diagnosen, wenn die aktivierten Regeln verletzt werden. Sie konfigurieren die Regeln, die auf Ihr Projekt angewendet werden sollen. Anschließend benachrichtigt jeder CI-Build Entwickler, wenn sie gegen eine der Regeln verstoßen.

Diagnose-IDs

Sprachrichtlinien

In den folgenden Abschnitten werden die Vorgehensweisen beschrieben, denen das .NET-Dokumentationsteam folgt, um Codebeispiele zu erstellen. Im Allgemeinen werden die folgenden Praktiken befolgt:

  • Verwendung moderner Sprachfeatures und C#-Versionen, falls möglich.
  • Vermeiden veralteter Sprachkonstrukte.
  • Abfangen von Ausnahmen, die ordnungsgemäß behandelt werden können; Vermeiden generischer Ausnahmen.
  • Verwenden spezifischer Ausnahmetypen, um aussagekräftige Fehlermeldungen bereitzustellen.
  • Verwenden von LINQ-Abfragen und -Methoden für die Sammlungsmanipulation, um die Lesbarkeit von Code zu verbessern.
  • Verwenden von asynchroner Programmierung mit Async und Await für E/A-gebundene Vorgänge.
  • Vorsicht bei Deadlocks und Verwenden von Task.ConfigureAwait bei Bedarf.
  • Verwenden von Sprachstichwörtern für Datentypen anstelle der Laufzeittypen. Z. B. string anstelle von System.String oder int anstelle von System.Int32.
  • Verwenden von int anstelle von Typen ohne Vorzeichen. Die Verwendung von int ist in C# üblich; durch den Einsatz von int wird die Interaktion mit anderen Bibliotheken vereinfacht. Ausnahmen gelten für Dokumentation speziell für nicht signierte Datentypen.
  • Verwenden Sie var nur, wenn ein Leser den Typ aus dem Ausdruck ableiten kann. Leser sehen unsere Beispiele auf der Dokumentenplattform. Es gibt keine Mauszeiger- oder Tooltipps, die den Typ der Variablen anzeigen.
  • Schreiben Sie Code mit Klarheit und Einfachheit.
  • Vermeiden Sie übermäßig komplexe und konvolutierte Codelogik.

Weitere spezifische Richtlinien folgen.

Zeichenfolgendaten

  • Verwenden Sie die Zeichenfolgeninterpolation, um wie im folgenden Code gezeigt kurze Zeichenfolgen zu verketten.

    string displayName = $"{nameList[n].LastName}, {nameList[n].FirstName}";
    
  • Verwenden Sie ein System.Text.StringBuilder-Objekt, um Zeichenfolgen in Schleifen anzufügen, besonders bei der Arbeit mit großen Textmengen.

    var phrase = "lalalalalalalalalalalalalalalalalalalalalalalalalalalalalala";
    var manyPhrases = new StringBuilder();
    for (var i = 0; i < 10000; i++)
    {
        manyPhrases.Append(phrase);
    }
    //Console.WriteLine("tra" + manyPhrases);
    

Arrays

  • Verwenden Sie die präzise Syntax, wenn Sie Arrays in der Deklarationszeile initialisieren. Im folgenden Beispiel können Sie nicht var anstelle von string[] verwenden.
string[] vowels1 = { "a", "e", "i", "o", "u" };
  • Wenn Sie explizite Instanziierung verwenden, können Sie var verwenden.
var vowels2 = new string[] { "a", "e", "i", "o", "u" };

Delegaten

  • Verwenden Sie Func<> und Action<>, anstatt Delegattypen zu definieren. Definieren Sie in einer Klasse die Delegatmethode.
Action<string> actionExample1 = x => Console.WriteLine($"x is: {x}");

Action<string, string> actionExample2 = (x, y) =>
    Console.WriteLine($"x is: {x}, y is {y}");

Func<string, int> funcExample1 = x => Convert.ToInt32(x);

Func<int, int, int> funcExample2 = (x, y) => x + y;
  • Rufen Sie die Methode mit der Signatur auf, die vom Func<>- oder Action<>-Delegaten definiert wird.
actionExample1("string for x");

actionExample2("string for x", "string for y");

Console.WriteLine($"The value is {funcExample1("1")}");

Console.WriteLine($"The sum is {funcExample2(1, 2)}");
  • Wenn Sie Instanzen eines Delegattyps erstellen, verwenden Sie die präzise Syntax. Definieren Sie in einer Klasse den Delegattyp und eine Methode, die eine übereinstimmende Signatur besitzt.

    public delegate void Del(string message);
    
    public static void DelMethod(string str)
    {
        Console.WriteLine("DelMethod argument: {0}", str);
    }
    
  • Erstellen Sie eine Instanz des Delegattyps, und rufen Sie sie auf. Die folgende Deklaration zeigt die komprimierte Syntax.

    Del exampleDel2 = DelMethod;
    exampleDel2("Hey");
    
  • In der folgenden Deklaration wird die vollständige Syntax verwendet.

    Del exampleDel1 = new Del(DelMethod);
    exampleDel1("Hey");
    

try-catch- und using-Anweisungen in der Ausnahmebehandlung

  • Verwenden Sie eine try-catch-Anweisung für die meisten Ausnahmebehandlungen.

    static double ComputeDistance(double x1, double y1, double x2, double y2)
    {
        try
        {
            return Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
        }
        catch (System.ArithmeticException ex)
        {
            Console.WriteLine($"Arithmetic overflow or underflow: {ex}");
            throw;
        }
    }
    
  • Vereinfachen Sie den Code mithilfe der C#-Anweisung using. Verwenden Sie bei einer try-finally-Anweisung, in der der einzige Code im finally-Block ein Aufruf der Dispose-Methode ist, stattdessen eine using-Anweisung.

    Im folgenden Beispiel ruft die try-finally-Anweisung nur Dispose im finally-Block auf.

    Font bodyStyle = new Font("Arial", 10.0f);
    try
    {
        byte charset = bodyStyle.GdiCharSet;
    }
    finally
    {
        if (bodyStyle != null)
        {
            ((IDisposable)bodyStyle).Dispose();
        }
    }
    

    Dasselbe können Sie mit einer using-Anweisung erreichen.

    using (Font arial = new Font("Arial", 10.0f))
    {
        byte charset2 = arial.GdiCharSet;
    }
    

    Verwenden Sie die neue using-Syntax, die keine geschweiften Klammern erfordert:

    using Font normalStyle = new Font("Arial", 10.0f);
    byte charset3 = normalStyle.GdiCharSet;
    

Die Operatoren && und ||

  • Verwenden Sie && anstelle von & und || anstelle von |, wenn Sie Vergleiche ausführen, wie im folgenden Beispiel gezeigt.

    Console.Write("Enter a dividend: ");
    int dividend = Convert.ToInt32(Console.ReadLine());
    
    Console.Write("Enter a divisor: ");
    int divisor = Convert.ToInt32(Console.ReadLine());
    
    if ((divisor != 0) && (dividend / divisor) is var result)
    {
        Console.WriteLine("Quotient: {0}", result);
    }
    else
    {
        Console.WriteLine("Attempted division by 0 ends up here.");
    }
    

Wenn der Divisor 0 ist, würde die zweite Klausel in der if-Anweisung einen Laufzeitfehler verursachen. Wenn der erste Ausdruck „false“ ist, wird der &&-Operator kurzgeschlossen. Dies bedeutet, dass er den zweiten Ausdruck nicht auswertet. Der &-Operator würde beide auswerten, was zu einem Laufzeitfehler führt, wenn divisor gleich 0 ist.

new-Operator

  • Verwenden Sie eine der präzisen Formen der Objektinstanziierung, wie in den folgenden Deklarationen gezeigt.

    var firstExample = new ExampleClass();
    
    ExampleClass instance2 = new();
    

    Die vorangehenden Deklarationen entsprechen der folgenden Deklaration.

    ExampleClass secondExample = new ExampleClass();
    
  • Verwenden Sie Objektinitialisierer, um die Objekterstellung zu vereinfachen, wie im folgenden Beispiel gezeigt.

    var thirdExample = new ExampleClass { Name = "Desktop", ID = 37414,
        Location = "Redmond", Age = 2.3 };
    

    Im folgenden Beispiel werden dieselben Eigenschaften wie im vorangehenden Beispiel festgelegt, dabei aber keine Initialisierer verwendet.

    var fourthExample = new ExampleClass();
    fourthExample.Name = "Desktop";
    fourthExample.ID = 37414;
    fourthExample.Location = "Redmond";
    fourthExample.Age = 2.3;
    

Ereignisbehandlung

  • Verwenden Sie einen Lambdaausdruck, wenn Sie einen Ereignishandler definieren, den Sie später nicht entfernen müssen:
public Form2()
{
    this.Click += (s, e) =>
        {
            MessageBox.Show(
                ((MouseEventArgs)e).Location.ToString());
        };
}

Der Lambdaausdruck verkürzt die folgende herkömmliche Definition.

public Form1()
{
    this.Click += new EventHandler(Form1_Click);
}

void Form1_Click(object? sender, EventArgs e)
{
    MessageBox.Show(((MouseEventArgs)e).Location.ToString());
}

Statische Member

Rufen Sie statische Member über diesen Klassennamen auf: ClassName.StaticMember. Durch diese Empfehlung ist der Code besser lesbar, da der statische Zugriff eindeutig ist. Qualifizieren Sie keinen statischen Member, der in einer Basisklasse mit dem Namen einer abgeleiteten Klasse definiert ist. Während dieser Code kompiliert wird, ist die Lesbarkeit des Codes irreführend, und der Code kann später beschädigt werden, wenn Sie der abgeleiteten Klasse einen statischen Member mit dem gleichen Namen hinzufügen.

LINQ-Abfragen

  • Verwenden Sie aussagekräftige Namen für Abfragevariablen. Im folgenden Beispiel wird seattleCustomers für Kunden in Seattle verwendet.

    var seattleCustomers = from customer in customers
                           where customer.City == "Seattle"
                           select customer.Name;
    
  • Verwenden Sie Aliase, um mithilfe der Pascal-Schreibweise sicherzustellen, dass die korrekte Großschreibung von Eigenschaftennamen anonymer Typen verwendet wird.

    var localDistributors =
        from customer in customers
        join distributor in distributors on customer.City equals distributor.City
        select new { Customer = customer, Distributor = distributor };
    
  • Benennen Sie Eigenschaften um, wenn die Eigenschaftennamen im Ergebnis nicht eindeutig sind. Wenn die Abfrage beispielsweise einen Kundennamen und eine Händler-ID zurückgibt, anstatt sie als Name und ID im Ergebnis beizubehalten, benennen Sie sie um, um zu verdeutlichen, dass Name der Name eines Kunden und ID die ID eines Händlers ist.

    var localDistributors2 =
        from customer in customers
        join distributor in distributors on customer.City equals distributor.City
        select new { CustomerName = customer.Name, DistributorID = distributor.ID };
    
  • Verwenden Sie die implizierte Typisierung in der Deklaration von Abfragevariablen und Bereichsvariablen. Dieser Leitfaden zum impliziten Eingeben in LINQ-Abfragen setzt die allgemeinen Regeln für implizit typisierte lokale Variablen außer Kraft. LINQ-Abfragen verwenden häufig Projektionen, die anonyme Typen erstellen. Andere Abfrageausdrücke erstellen Ergebnisse mit geschachtelten generischen Typen. Implizite Typvariablen sind häufig besser lesbar.

    var seattleCustomers = from customer in customers
                           where customer.City == "Seattle"
                           select customer.Name;
    
  • Richten Sie Abfrageklauseln unter der from-Klausel aus, wie in den vorherigen Beispielen gezeigt.

  • Verwenden Sie vor anderen Abfrageklauseln where-Klauseln, um sicherzustellen, dass nachfolgende Abfrageklauseln für den reduzierten, gefilterten Datensatz ausgeführt werden.

    var seattleCustomers2 = from customer in customers
                            where customer.City == "Seattle"
                            orderby customer.Name
                            select customer;
    
  • Verwenden Sie mehrere from-Klauseln anstelle einer join-Klausel, um auf die inneren Auflistungen zuzugreifen. Eine Auflistung von Student-Objekten kann beispielsweise jeweils eine Auflistung von Testergebnissen enthalten. Wenn die folgende Abfrage ausgeführt wird, wird jedes Ergebnis über 90 zusammen mit dem Nachnamen des Studenten zurückgegeben, der das Testergebnis erzielt hat.

    var scoreQuery = from student in students
                     from score in student.Scores!
                     where score > 90
                     select new { Last = student.LastName, score };
    

Implizit typisierte lokale Variablen

  • Verwenden Sie die implizite Typisierung für lokale Variablen, wenn der Typ der Variablen auf der rechten Seite der Zuweisung offensichtlich ist.

    var message = "This is clearly a string.";
    var currentTemperature = 27;
    
  • Verwenden Sie nicht var, wenn der Typ nicht von der rechten Seite der Zuweisung offensichtlich ist. Gehen Sie nicht davon aus, dass der Typ aus einem Methodennamen ersichtlich und somit eindeutig ist. Ein Variablentyp wird als eindeutig angesehen, wenn es sich um einen new-Operator, eine explizite Umwandlung oder einen Literalwert handelt.

    int numberOfIterations = Convert.ToInt32(Console.ReadLine());
    int currentMaximum = ExampleClass.ResultSoFar();
    
  • Verwenden Sie keine Variablennamen, um den Typ der Variablen anzugeben. Er ist unter Umständen nicht korrekt. Verwenden Sie stattdessen den Typ, um den Typ anzugeben, und verwenden Sie den Variablennamen, um die semantischen Informationen der Variablen anzugeben. Im folgenden Beispiel sollte string für den Typ und etwas wie iterations verwendet werden, um die Bedeutung der aus der Konsole gelesenen Informationen anzugeben.

    var inputInt = Console.ReadLine();
    Console.WriteLine(inputInt);
    
  • Vermeiden Sie den Einsatz von var anstelle von dynamic. Verwenden Sie dynamic, wenn Sie den Laufzeit-Typrückschluss verwenden möchten. Weitere Informationen finden Sie unter Verwenden des Typs „dynamic“ (C#-Programmierhandbuch).

  • Verwenden Sie die implizite Eingabe für die Schleifenvariable in for-Schleifen.

    Im folgenden Beispiel wird die implizite Typisierung in einer for-Anweisung verwendet.

    var phrase = "lalalalalalalalalalalalalalalalalalalalalalalalalalalalalala";
    var manyPhrases = new StringBuilder();
    for (var i = 0; i < 10000; i++)
    {
        manyPhrases.Append(phrase);
    }
    //Console.WriteLine("tra" + manyPhrases);
    
  • Verwenden Sie nicht die implizite Typisierung, um den Typ der Schleifenvariablen in foreach-Schleifen zu bestimmen. In den meisten Fällen ist der Typ der Elemente in der Sammlung nicht sofort offensichtlich. Der Name der Sammlung sollte nicht nur vom Rückschluss auf den Typ ihrer Elemente abhängen.

    Im folgenden Beispiel wird die explizite Typisierung in einer foreach-Anweisung verwendet.

    foreach (char ch in laugh)
    {
        if (ch == 'h')
            Console.Write("H");
        else
            Console.Write(ch);
    }
    Console.WriteLine();
    
  • Verwenden Sie impliziten Typ für die Ergebnissequenzen in LINQ-Abfragen. Im Abschnitt zu LINQ wird erläutert, dass viele LINQ-Abfragen zu anonymen Typen führen, bei denen implizite Typen verwendet werden müssen. Andere Abfragen führen zu geschachtelten generischen Typen, bei denen var besser lesbar ist.

    Hinweis

    Achten Sie darauf, nicht versehentlich den Typ eines Elements in der Iterable-Sammlung zu ändern. Beispielsweise ist es einfach, in einer foreach-Anweisung von System.Linq.IQueryable zu System.Collections.IEnumerable zu wechseln, was die Ausführung einer Abfrage ändert.

Einige unserer Beispiele erläutern den natürlichen Typ eines Ausdrucks. Diese Beispiele müssen var verwenden, damit der Compiler den natürlichen Typ auswählt. Obwohl diese Beispiele weniger offensichtlich sind, ist die Verwendung von var für das Beispiel erforderlich. Der Text sollte das Verhalten erläutern.

Platzieren der using-Anweisungen außerhalb der Namespace-Deklaration

Wenn sich eine using-Anweisung außerhalb einer Namespace-Deklaration befindet, ist dieser importierte Namespace der vollqualifizierte Name. Der vollqualifizierte Name ist deutlicher. Wenn sich die using-Anweisung innerhalb des Namespace befindet, kann sie entweder relativ zu diesem Namespace sein oder es kann sich um einen vollqualifizierten Namen handeln.

using Azure;

namespace CoolStuff.AwesomeFeature
{
    public class Awesome
    {
        public void Stuff()
        {
            WaitUntil wait = WaitUntil.Completed;
            // ...
        }
    }
}

Vorausgesetzt, es gibt einen Verweis (direkt oder indirekt) auf die WaitUntil-Klasse.

Nun nehmen wir eine kleine Änderung vor:

namespace CoolStuff.AwesomeFeature
{
    using Azure;

    public class Awesome
    {
        public void Stuff()
        {
            WaitUntil wait = WaitUntil.Completed;
            // ...
        }
    }
}

Und kompilieren heute. Und morgen. Aber irgendwann nächste Woche schlägt der vorherige (unveränderte) Code mit zwei Fehlern fehl:

- error CS0246: The type or namespace name 'WaitUntil' could not be found (are you missing a using directive or an assembly reference?)
- error CS0103: The name 'WaitUntil' does not exist in the current context

Eine der Abhängigkeiten hat diese Klasse in einem Namespace eingeführt und endet dann mit .Azure:

namespace CoolStuff.Azure
{
    public class SecretsManagement
    {
        public string FetchFromKeyVault(string vaultId, string secretId) { return null; }
    }
}

Eine using-Direktive, die in einem Namespace platziert wurde, ist kontextbezogen und erschwert die Namensauflösung. In diesem Beispiel ist es der erste gefundene Namespace.

  • CoolStuff.AwesomeFeature.Azure
  • CoolStuff.Azure
  • Azure

Das Hinzufügen eines neuen Namespace, der entweder mit CoolStuff.Azure oder CoolStuff.AwesomeFeature.Azure übereinstimmt, wäre eine Übereinstimmung vor dem globalen Azure-Namespace. Sie können dies beheben, indem Sie der Deklaration den global::-Modifizierer zur using-Deklaration hinzufügen. Es ist jedoch einfacher, using-Deklarationen stattdessen außerhalb des Namespace zu platzieren.

namespace CoolStuff.AwesomeFeature
{
    using global::Azure;

    public class Awesome
    {
        public void Stuff()
        {
            WaitUntil wait = WaitUntil.Completed;
            // ...
        }
    }
}

Stilrichtlinien

Verwenden Sie im Allgemeinen das folgende Format für Codebeispiele:

  • Verwenden Sie vier Leerzeichen für den Einzug. Verwenden Sie keine Tabulatoren.
  • Richten Sie den Code konsistent aus, um die Lesbarkeit zu verbessern.
  • Beschränken Sie Zeilen auf 65 Zeichen, um die Lesbarkeit von Code in Dokumenten zu verbessern, insbesondere auf mobilen Bildschirmen.
  • Unterteilen Sie lange Anweisungen in mehrere Zeilen, um die Klarheit zu verbessern.
  • Verwenden Sie die Formatvorlage „Allman“ für geschweifte Klammern: für öffnende und schließende geschweifte Klammer eine eigene neue Zeile. Geschweifte Klammern werden an der aktuellen Einzugsebene ausgerichtet.
  • Zeilenumbrüche sollten bei Bedarf vor binären Operatoren auftreten.

Kommentarstil

  • Verwenden Sie einzeilige Kommentare (//) für kurze Erläuterungen.

  • Vermeiden Sie mehrzeilige Kommentare (/* */) für längere Erklärungen. Kommentare werden nicht lokalisiert. Stattdessen werden längere Erläuterungen im Begleitartikel aufgeführt.

  • Zum Beschreiben von Methoden, Klassen, Feldern und allen öffentlichen Membern werden XML-Kommentare verwendet.

  • Fügen Sie den Kommentar in einer eigenen Zeile und nicht am Ende einer Codezeile ein.

  • Beginnen Sie Kommentartext mit einem Großbuchstaben.

  • Beenden Sie den Kommentartext mit einem Punkt.

  • Fügen Sie ein Leerzeichen zwischen dem Kommentartrennzeichen (//) und dem Kommentartext ein, wie im folgenden Beispiel gezeigt.

    // The following declaration creates a query. It does not run
    // the query.
    

Layoutkonventionen

Ein gutes Layout verwendet Formatierungen, um die Struktur des Codes hervorzuheben und um den Code verständlicher zu gestalten. Microsoft-Beispiele entsprechen den folgenden Konventionen:

  • Verwenden Sie die Code-Editor-Standardeinstellungen (Intelligenter Einzug, vierstelliger Einzug, als Leerzeichen gespeicherte Tabulatoren). Weitere Informationen finden Sie unter Optionen, Text-Editor, C#, Formatierung.

  • Schreiben Sie pro Zeile nur eine Anweisung.

  • Schreiben Sie pro Zeile nur eine Deklaration.

  • Wenn Fortsetzungszeilen nicht automatisch eingezogen werden, rücken Sie diese um einen Tabstopp (vier Leerzeichen) ein.

  • Fügen Sie zwischen Methoden- und Eigenschaftsdefinitionen mindestens eine Leerzeile ein.

  • Verwenden Sie Klammern, um Klauseln in einem Ausdruck zu kennzeichnen, wie im folgenden Code gezeigt.

    if ((startX > endX) && (startX > previousX))
    {
        // Take appropriate action.
    }
    

Ausnahmen sind, wenn im Beispiel die Rangfolge von Operatoren oder Ausdrücken erläutert wird.

Sicherheit

Befolgen Sie die Richtlinien in Richtlinien für das Schreiben von sicherem Code.