C# Stil-Richtlinien¶
Für jedes Projekt ist es wichtig, klar definierte und konsistente Codierungskonventionen zu haben und Godot ist keine Ausnahme von dieser Regel.
Diese Seite enthält eine Anleitung mit Gestaltungsrichtlinien zum Codieren, dem Entwickler und Mitwirkende von Godot selbst folgen. Als solches ist es hauptsächlich für diejenigen gedacht, die zu dem Projekt beitragen möchten. Da die in diesem Artikel erwähnten Konventionen und Richtlinien jedoch von den Benutzern der Sprache am häufigsten übernommen werden, empfehlen wir Ihnen dasselbe zu tun, insbesondere wenn Sie bisher noch keinen solchen Leitfaden hatten.
Bemerkung
Dieser Artikel ist keineswegs eine vollständige Anleitung zur Befolgung der Standardcodierungskonventionen oder Best Practices. Wenn Sie sich bei einem der hier behandelten Aspekt nicht sicher sind, lesen Sie bitte eine umfassendere Dokumentation, z.B. C# Codierungskonventionen oder Framework Designrichtlinien.
Sprachspezifisch¶
Godot verwendet derzeit C# Version 7.0 in seiner Engine und im Beispielquellcode. Bevor wir zu einer neueren Version wechseln muss darauf geachtet werden, dass keine Sprachfunktionen gemischt werden, die nur in C# 7.1 oder höher verfügbar sind.
Ausführliche Informationen zu C# Funktionen in verschiedenen Versionen finden Sie unter Was ist neu in C#.
Formatierung¶
Generelle Richtlinien¶
Nutze Line Feed (LF) zum Zeilenumbruch, nicht CRLF oder CR.
Benutze ein Line Feed am Ende jeder Datei, mit Ausnahme der csproj Datei.
Verwenden Sie die UTF-8 -Codierung ohne eine Byte order mark.
Es sollten 4 Leerzeichen anstelle von Tabulatoren zum Einrücken (die als "weiche Tabulatoren" bezeichnet werden) verwendet werden.
Wenn eine Zeile länger als 100 Zeichen ist, sollte sie in mehrere Zeilen aufgeteilt werden.
Zeilenumbrüche und Leerzeilen¶
Befolgen Sie für eine allgemeine Einrückungsregel den "Allman-Stil" <https://en.wikipedia.org/wiki/Indentation_style#Allman_style>`_ welcher empfiehlt, die mit einer Steueranweisung verknüpfte Klammer in der nächsten Zeile zu platzieren, mit der gleichen Einrückungsstufe:
// Use this style:
if (x > 0)
{
DoSomething();
}
// NOT this:
if (x > 0) {
DoSomething();
}
Wie auch immer, es sollten Zeilenumbrüche innerhalb von Klammern vermieden werden:
Für einfache Zugriffsfunktionen (Property Accessors).
Für einfache Objekte, Arrays oder Collection Initializer.
Für abstrakte automatische Eigenschaften, Indexer oder selbst Deklarationen.
// You may put the brackets in a single line in following cases:
public interface MyInterface
{
int MyProperty { get; set; }
}
public class MyClass : ParentClass
{
public int Value
{
get { return 0; }
set
{
ArrayValue = new [] {value};
}
}
}
Eine Leerzeile einfügen:
Nach einer Liste von
using
-Anweisungen.Zwischen Methoden, Eigenschaften und innerer Typen-Deklarationen.
Am Ende jeder Datei.
Feld- und Konstantendeklarationen können nach Relevanz gruppiert werden. In diesem Fall sollten Sie eine leere Zeile zwischen den Gruppen einfügen, um das Lesen zu erleichtern.
Vermeide Leerzeilen einzufügen:
Nach
{
, der öffnenden Klammer.Vor
}
, der schließenden Klammer.Nach einem Kommentar-Block oder einem einzeiligem Kommentar.
Angrenzend an eine weitere Leerzeile.
using System;
using Godot;
// Blank line after `using` list.
public class MyClass
{ // No blank line after `{`.
public enum MyEnum
{
Value,
AnotherValue // No blank line before `}`.
}
// Blank line around inner types.
public const int SomeConstant = 1;
public const int AnotherConstant = 2;
private Vector3 _x; // Related constants or fields can be
private Vector3 _y; // grouped together.
private float _width;
private float _height;
public int MyProperty { get; set; }
// Blank line around properties.
public void MyMethod()
{
// Some comment.
AnotherMethod(); // No blank line after a comment.
}
// Blank line around methods.
public void AnotherMethod()
{
}
}
Verwendung von Leerzeichen¶
Leerzeichen einfügen:
Um binäre und tertiäre Operatoren.
Zwischen einer öffnenden Klammer und
if
,for
,foreach
,catch
,while
,lock
oderusing
Schlüsselwörtern.Vor und innerhalb eines Zugriffsblocks in einer einzelnen Zeile.
Zwischen Zugriffsfunktionen in einem einzeiligen Zugriffsblock.
Nach einem Komma das nicht am Ende der Zeile steht.
Nach einem Semikolon in einer
for
Statement.Nach einem Doppelpunkt in einem einzelnen
case
Statement.Um einem Doppelpunkt in einer Typ Deklaration.
Um den Lambda Pfeil.
Nach einem einzeiligem Kommentar-Symbol (
//
) und bevor es am Ende einer Zeile genutzt wird.
Nutze kein Leerzeichen:
Nach Typ Cast Klammern.
Innerhalb einzeiliger Initialisierungsklammern.
Das folgende Beispiel zeigt eine ordnungsgemäße Verwendung von Leerzeichen gemäß einigen der oben genannten Konventionen:
public class MyClass<A, B> : Parent<A, B>
{
public float MyProperty { get; set; }
public float AnotherProperty
{
get { return MyProperty; }
}
public void MyMethod()
{
int[] values = {1, 2, 3, 4}; // No space within initializer brackets.
int sum = 0;
// Single line comment.
for (int i = 0; i < values.Length; i++)
{
switch (i)
{
case 3: return;
default:
sum += i > 2 ? 0 : 1;
break;
}
}
i += (int)MyProperty; // No space after a type cast.
}
}
Benennungsrichtlinien¶
Verwenden Sie PascalCase für alle Namensräume, Typnamen und Kennungen auf Elementebene (also Methoden, Eigenschaften, Konstanten, Ereignisse), außer für private Felder:
namespace ExampleProject
{
public class PlayerCharacter
{
public const float DefaultSpeed = 10f;
public float CurrentSpeed { get; set; }
protected int HitPoints;
private void CalculateWeaponDamage()
{
}
}
}
Verwenden Sie camelCase für alle anderen Bezeichner (also lokale Variablen, Methodenargumente) und einen Unterstrich (_
) als Präfix für private Felder (jedoch nicht für Methoden oder Eigenschaften, wie oben erläutert):
private Vector3 _aimingAt; // Use a `_` prefix for private fields.
private void Attack(float attackStrength)
{
Enemy targetFound = FindTarget(_aimingAt);
targetFound?.Hit(attackStrength);
}
Es gibt eine Ausnahme mit Akronymen die aus zwei Buchstaben bestehen wie UI
, die in Großbuchstaben geschrieben werden sollten, wo PascalCase erwartet werden würde und ansonsten in Kleinbuchstaben.
Beachten Sie, dass id
kein Akronym ist, daher sollte es als normaler Bezeichner behandelt werden:
public string Id { get; }
public UIManager UI
{
get { return uiManager; }
}
Es wird allgemein davon abgeraten, einen Typnamen als Präfix eines Bezeichners zu verwenden, wie z. B. string strText
oder float fPower
. Eine Ausnahme wird jedoch für Schnittstellen gemacht, denen tatsächlich der Großbuchstabe I
vor ihren Namen vorangestellt werden sollte, z.B. IInventoryHolder
oder IDamageable
.
Erwägen Sie schließlich die Auswahl beschreibender Namen und versuchen Sie nicht, diese zu stark zu kürzen, wenn dies die Lesbarkeit beeinträchtigt.
Wenn Sie beispielsweise Code schreiben möchten, um einen nahe gelegenen Feind zu finden und ihn mit einer Waffe zu treffen, bevorzugen Sie:
FindNearbyEnemy()?.Damage(weaponDamage);
Besser als:
FindNode()?.Change(wpnDmg);
Mitgliedsvariablen¶
Deklarieren Sie keine Mitgliedsvariablen, wenn sie nur lokal in einer Methode verwendet werden, da dies das Lesen des Codes erschwert. Deklarieren Sie sie stattdessen als lokale Variablen in der Methode.
Lokale Variablen¶
Deklarieren Sie lokale Variablen so nah wie möglich am Platz ihrer ersten Verwendung. Dies erleichtert das Lesen des Codes, ohne zu viel scrollen zu müssen, um herauszufinden, wo die Variable deklariert wurde.
Implizit typisierte lokale Variablen¶
Erwägen Sie die implizite Typisierung (var
) für die Deklaration einer lokalen Variablen, aber tun Sie dies nur, wenn der Typ ersichtlich ist (auf der rechten Seite der Zuweisung ):
// You can use `var` for these cases:
var direction = new Vector2(1, 0);
var value = (int)speed;
var text = "Some value";
for (var i = 0; i < 10; i++)
{
}
// But not for these:
var value = GetValue();
var velocity = direction * 1.5;
// It's generally a better idea to use explicit typing for numeric values, especially with
// the existence of the `real_t` alias in Godot, which can either be double or float
// depending on the build configuration.
var value = 1.5;
Andere Überlegungen¶
Verwenden Sie explizite Zugriffsmodifikatoren.
Verwenden Sie Eigenschaften anstelle von nicht privaten Feldern.
Verwenden Sie Modifikatoren in dieser Reihenfolge:
public
/protected
/private
/internal
/virtual
/override
/abstract
/new
/static
/readonly
.Vermeiden Sie die Verwendung vollständig qualifizierter Namen oder des Präfixes
this.
für Mitglieder, wenn dies nicht erforderlich ist.Entfernen Sie nicht verwendete
using
-Anweisungen und unnötige Klammern.Lassen Sie den Standardanfangswert für einen Typ weg.
Verwenden Sie möglicherweise nullbedingte Operatoren (null-conditional) oder Typinitialisierer, um den Code kompakter zu gestalten.
Verwenden Sie einen sicheren Cast, wenn die Möglichkeit besteht, dass der Wert ein anderer Typ ist und verwenden Sie andernfalls einen direkten Cast.