Zum Hauptinhalt springen

C#-Richtlinien

Codestil​

1. Verwenden Sie die Editor-Config-Datei aus dem Repository meshmakers/common

Bis wir eine bessere Möglichkeit haben, die Einstellungen zu teilen, verwenden Sie die .editorconfig aus dem Repository meshmakers/common.
Aktivieren Sie in Rider die .editorconfig unter Settings -> Editor -> Code Style -> Enable EditorConfig support.

2. Führen Sie vor dem Commit ein vollständiges Code-Cleanup Ihrer geänderten Dateien durch

Warum: Da die IDEs das Erzwingen des formalen Stils des Quellcodes unterstützen, können sich die Entwickler bei den Code-Reviews auf die Funktionalität konzentrieren.
Außerdem ist Quellcode mit gemischten Stilen wirklich schwer zu lesen.

3. Verwenden Sie eine maximale Zeilenlänge von 140 Zeichen

Warum: Auch wenn die meisten Monitore eine 4k-Auflösung haben, ist es wirklich mühsam, sehr lange Zeilen Quellcode zu lesen. Erst recht beim Inspizieren von Änderungen

Ausnahmen​

Verwenden Sie KEINE spezifischen Exceptions aus der .NET-Bibliothek oder aus externen Bibliotheken erneut, mit Ausnahme von:

  1. System.Exception
  2. System.ArgumentException
  3. System.ArgumentNullException
  4. System.ArgumentOutOfRangeException

C#-Codierungsstandards und Namenskonventionen​

ObjektnameNotationLängePluralPräfixSuffixAbkürzungZeichenmaskeUnterstriche
Namespace-NamePascalCase128JaJaNeinNein[A-z][0-9]Nein
KlassennamePascalCase128NeinNeinJaNein[A-z][0-9]Nein
KonstruktornamePascalCase128NeinNeinJaNein[A-z][0-9]Nein
MethodennamePascalCase128JaNeinNeinNein[A-z][0-9]Nein
MethodenargumentecamelCase128JaNeinNeinJa[A-z][0-9]Nein
Lokale VariablencamelCase50JaNeinNeinJa[A-z][0-9]Nein
Konstantenname *)SCREAMING_SNAKE_CASE50NeinNeinNeinNein[A-z][0-9][_]Ja
FeldnamecamelCase50JaNeinNeinJa[A-z][0-9]Ja
EigenschaftsnamePascalCase50JaNeinNeinJa[A-z][0-9]Nein
Delegate-NamePascalCase128NeinNeinJaJa[A-z]Nein
Enum-TypnamePascalCase128JaNeinNeinNein[A-z]Nein

*) Von meshmakers gegenüber den .NET-Namenskonventionen geändert

1. Verwenden Sie PascalCasing für Klassennamen und Methodennamen:​

public class ClientActivity
{
public void ClearStatistics()
{
//...
}
public void CalculateStatistics()
{
//...
}
}

Warum: konsistent mit Microsofts .NET Framework und leicht zu lesen.

2. Verwenden Sie camelCasing für Methodenargumente und lokale Variablen:​

public class UserLog
{
public void Add(LogEvent logEvent)
{
int itemCount = logEvent.Items.Count;
// ...
}
}

Warum: konsistent mit Microsofts .NET Framework und leicht zu lesen.

3. Verwenden Sie keine ungarische Notation oder andere Typkennzeichnungen in Bezeichnern​

// Correct
int counter;
string name;
// Avoid
int iCounter;
string strName;

Warum: konsistent mit Microsofts .NET Framework, und die Visual Studio IDE macht das Ermitteln von Typen sehr einfach (über Tooltips). Grundsätzlich sollten Sie Typindikatoren in jedem Bezeichner vermeiden.

4. Verwenden Sie keine Screaming Caps für Konstanten oder readonly-Variablen:​

// Correct
public const string ShippingType = "DropShip";
// Avoid
public const string SHIPPINGTYPE = "DropShip";

Warum: konsistent mit Microsofts .NET Framework. Großbuchstaben ziehen zu viel Aufmerksamkeit auf sich.

5. Verwenden Sie aussagekräftige Namen für Variablen. Das folgende Beispiel verwendet seattleCustomers für Kunden, die sich in Seattle befinden:​

var seattleCustomers = from customer in customers
where customer.City == "Seattle"
select customer.Name;

Warum: konsistent mit Microsofts .NET Framework und leicht zu lesen.

6. Vermeiden Sie Abkürzungen. Ausnahmen: Abkürzungen, die üblicherweise als Namen verwendet werden, wie Id, Xml, Ftp, Uri.​

// Correct
UserGroup userGroup;
Assignment employeeAssignment;
// Avoid
UserGroup usrGrp;
Assignment empAssignment;
// Exceptions
CustomerId customerId;
XmlDocument xmlDocument;
FtpHelper ftpHelper;
UriPart uriPart;

Warum: konsistent mit Microsofts .NET Framework und verhindert inkonsistente Abkürzungen.

7. Verwenden Sie PascalCasing oder camelCasing (abhängig vom Bezeichnertyp) für Abkürzungen mit 3 oder mehr Zeichen (bei 2 Zeichen werden beide großgeschrieben, wenn PascalCasing angebracht ist oder innerhalb des Bezeichners).:​

HtmlHelper htmlHelper;
FtpTransfer ftpTransfer, fastFtpTransfer;
UIControl uiControl, nextUIControl;

Warum: konsistent mit Microsofts .NET Framework. Großbuchstaben würden visuell zu viel Aufmerksamkeit auf sich ziehen.

8. Verwenden Sie keine Unterstriche in Bezeichnern. Ausnahme: Sie können private Felder mit einem Unterstrich als Präfix versehen:​

// Correct
public DateTime clientAppointment;
public TimeSpan timeLeft;
// Avoid
public DateTime client_Appointment;
public TimeSpan time_Left;
// Exception (Class field)
private DateTime _registrationDate;

Warum: konsistent mit Microsofts .NET Framework und macht den Code natürlicher lesbar (ohne „Verschleifen"). Vermeidet außerdem Unterstrich-Stress (die Unfähigkeit, den Unterstrich zu erkennen).

9. Verwenden Sie vordefinierte Typnamen (C#-Aliase) wie int, float, string für lokale Deklarationen sowie Parameter- und Member-Deklarationen. Verwenden Sie .NET-Framework-Namen wie Int32, Single, String, wenn Sie auf die statischen Member des Typs zugreifen, etwa Int32.TryParse oder String.Join.​

// Correct
string firstName;
int lastIndex;
bool isSaved;
string commaSeparatedNames = String.Join(", ", names);
int index = Int32.Parse(input);
// Avoid
String firstName;
Int32 lastIndex;
Boolean isSaved;
string commaSeparatedNames = string.Join(", ", names);
int index = int.Parse(input);

Warum: konsistent mit Microsofts .NET Framework und macht den Code natürlicher lesbar.

10. Verwenden Sie den impliziten Typ var für Deklarationen lokaler Variablen. Ausnahme: Bei primitiven Typen (int, string, double usw.) verwenden Sie die vordefinierten Namen.​

var stream = File.Create(path);
var customers = new Dictionary();
// Exceptions
int index = 100;
string timeSheet;
bool isCompleted;

Warum: reduziert Unordnung, insbesondere bei komplexen generischen Typen. Der Typ lässt sich mit den Visual-Studio-Tooltips leicht erkennen.

11. Verwenden Sie ein Substantiv oder eine Substantivphrase, um eine Klasse zu benennen.​

public class Employee
{
}
public class BusinessLocation
{
}
public class DocumentCollection
{
}

Warum: konsistent mit Microsofts .NET Framework und leicht zu merken.

12. Versehen Sie Interfaces mit dem Buchstaben I als Präfix. Interface-Namen sind Substantive (Substantivphrasen) oder Adjektive.​

public interface IShape
{
}
public interface IShapeCollection
{
}
public interface IGroupable
{
}

Warum: konsistent mit Microsofts .NET Framework.

13. Benennen Sie Quelldateien entsprechend ihren Hauptklassen. Ausnahme: Dateinamen mit partiellen Klassen spiegeln ihre Herkunft oder ihren Zweck wider, z. B. designer, generated usw.​

// Located in Task.cs
public partial class Task
{
}
// Located in Task.generated.cs
public partial class Task
{
}

Warum: konsistent mit den Microsoft-Praktiken. Dateien werden alphabetisch sortiert und partielle Klassen bleiben benachbart.

14. Organisieren Sie Namespaces mit einer klar definierten Struktur:​

// Examples
namespace Company.Technology.Feature.Subnamespace
{
}
namespace Company.Product.Module.SubModule
{
}
namespace Product.Module.Component
{
}
namespace Product.Layer.Module.Group
{
}

Warum: konsistent mit Microsofts .NET Framework. Erhält eine gute Organisation Ihrer Codebasis.

15. Richten Sie geschweifte Klammern vertikal aus:​

// Correct
class Program
{
static void Main(string[] args)
{
//...
}
}

Warum: Microsoft hat einen anderen Standard, aber Entwickler bevorzugen überwiegend vertikal ausgerichtete Klammern.

16. Deklarieren Sie alle Member-Variablen am Anfang einer Klasse, mit den statischen Variablen ganz oben.​

// Correct
public class Account
{
public static string BankName;
public static decimal Reserves;
public string Number { get; set; }
public DateTime DateOpened { get; set; }
public DateTime DateClosed { get; set; }
public decimal Balance { get; set; }
// Constructor
public Account()
{
// ...
}
}

Warum: allgemein akzeptierte Praxis, die es überflüssig macht, nach Variablendeklarationen zu suchen.

17. Verwenden Sie Singular-Namen für Enums. Ausnahme: Bitfeld-Enums.​

// Correct
public enum Color
{
Red,
Green,
Blue,
Yellow,
Magenta,
Cyan
}
// Exception
[Flags]
public enum Dockings
{
None = 0,
Top = 1,
Right = 2,
Bottom = 4,
Left = 8
}

Warum: konsistent mit Microsofts .NET Framework und macht den Code natürlicher lesbar. Plural bei Flags, weil ein Enum mehrere Werte enthalten kann (mittels bitweisem „OR").

18. Geben Sie den Typ eines Enums oder die Werte von Enums nicht explizit an (außer bei Bitfeldern):​

// Don't
public enum Direction : long
{
North = 1,
East = 2,
South = 3,
West = 4
}
// Correct
public enum Direction
{
North,
East,
South,
West
}

Warum: kann zu Verwirrung führen, wenn man sich auf die tatsächlichen Typen und Werte verlässt.

19. Verwenden Sie kein „Enum"-Suffix in Enum-Typnamen:​

// Don't
public enum CoinEnum
{
Penny,
Nickel,
Dime,
Quarter,
Dollar
}
// Correct
public enum Coin
{
Penny,
Nickel,
Dime,
Quarter,
Dollar
}

Warum: konsistent mit Microsofts .NET Framework und konsistent mit der vorherigen Regel, keine Typindikatoren in Bezeichnern zu verwenden.

20. Verwenden Sie keine „Flag"- oder „Flags"-Suffixe in Enum-Typnamen:​

// Don't
[Flags]
public enum DockingsFlags
{
None = 0,
Top = 1,
Right = 2,
Bottom = 4,
Left = 8
}
// Correct
[Flags]
public enum Dockings
{
None = 0,
Top = 1,
Right = 2,
Bottom = 4,
Left = 8
}

Warum: konsistent mit Microsofts .NET Framework und konsistent mit der vorherigen Regel, keine Typindikatoren in Bezeichnern zu verwenden.

21. Verwenden Sie das Suffix EventArgs bei der Erstellung neuer Klassen, die die Informationen zu einem Event enthalten:​

// Correct
public class BarcodeReadEventArgs : System.EventArgs
{
}

Warum: konsistent mit Microsofts .NET Framework und leicht zu lesen.

22. Benennen Sie Event-Handler (Delegates, die als Typen von Events verwendet werden) mit dem Suffix „EventHandler", wie im folgenden Beispiel gezeigt:​

public delegate void ReadBarcodeEventHandler(object sender, ReadBarcodeEventArgs e);

Warum: konsistent mit Microsofts .NET Framework und leicht zu lesen.

23. Erstellen Sie keine Parameternamen in Methoden (oder Konstruktoren), die sich nur durch die Groß-/Kleinschreibung unterscheiden:​

// Avoid
private void MyFunction(string name, string Name)
{
//...
}

Warum: konsistent mit Microsofts .NET Framework und leicht zu lesen, und schließt außerdem die Möglichkeit von Konfliktsituationen aus.

24. Verwenden Sie zwei Parameter mit den Namen sender und e in Event-Handlern. Der Parameter sender repräsentiert das Objekt, das das Event ausgelöst hat. Der Parameter sender ist typischerweise vom Typ object, auch wenn es möglich wäre, einen spezifischeren Typ zu verwenden.​

public void ReadBarcodeEventHandler(object sender, ReadBarcodeEventArgs e)
{
//...
}

Warum: konsistent mit Microsofts .NET Framework und konsistent mit der vorherigen Regel, keine Typindikatoren in Bezeichnern zu verwenden.

25. Verwenden Sie das Suffix Exception bei der Erstellung neuer Klassen, die die Informationen zu einer Exception enthalten:​

// Correct
public class BarcodeReadException : System.Exception
{
}

Warum: konsistent mit Microsofts .NET Framework und leicht zu lesen.

26. Verwenden Sie das Präfix Any, Is, Have oder ähnliche Schlüsselwörter für einen boolean-Bezeichner:​

// Correct
public static bool IsNullOrEmpty(string value) {
return (value == null || value.Length == 0);
}

Warum: konsistent mit Microsofts .NET Framework und leicht zu lesen.

Konfiguration​

  • C#-Sprachversion (Referenz): latest major
  • Nullable Reference Types aktiviert