Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
Guida di stile C#
Avere convenzioni di codifica ben definite e coerenti è importante per ogni progetto e Godot non fa eccezione a questa regola.
Questa pagina contiene una guida di stile di programmazione, seguita dagli sviluppatori e dai collaboratori di Godot. Pertanto, è rivolta principalmente a coloro che desiderano contribuire al progetto, ma poiché le convenzioni e le linee guida menzionate in questo articolo sono quelle più ampiamente adottate dagli utenti del linguaggio, invitiamo a fare lo stesso, soprattutto se non si dispone ancora di una guida del genere.
Nota
Questo articolo non è in alcun modo una guida esaustiva su come seguire le convenzioni di codifica standard o le migliori pratiche. In caso di dubbi su un aspetto non trattato qui, consultare documentazione più completa, come C# Coding Conventions o Framework Design Guidelines.
Specifiche del linguaggio
Godot utilizza attualmente C# versione 12.0 nel suo motore e nel codice sorgente di esempio, poiché questa è la versione supportata da .NET 8.0 (l'attuale requisito di base). Pertanto, prima di passare a una versione più recente, è necessario prestare attenzione a non mischiare funzionalità del linguaggio disponibili solo in C# 13.0 o versioni successive.
Per informazioni dettagliate sulle funzionalità di C# nelle diverse versioni, consultare What's New in C#.
Formattazione
Linee guida generali
Utilizzare caratteri di avanzamento riga (LF) per separare le righe, non CRLF o CR.
Utilizzare un solo carattere di avanzamento riga alla fine di ogni file, tranne per i file csproj.
Utilizzare la codifica UTF-8 senza byte order mark.
Utilizzare 4 spazi anziché tabulazioni per l'indentazione (riferiti come "soft tab").
Considera di suddividere una riga in più righe se è più lunga di 100 caratteri.
Ritorni a capo e righe vuote
Per una regola generale di indentazione, seguire lo "stile Allman" che consiglia di posizionare la parentesi graffa associata a un'istruzione di controllo sulla riga successiva, indentata allo stesso livello:
// Use this style:
if (x > 0)
{
DoSomething();
}
// NOT this:
if (x > 0) {
DoSomething();
}
Tuttavia, è possibile scegliere di omettere le interruzioni di riga all'interno delle parentesi:
Per gli accessori di proprietà semplici.
Per gli inizializzatori di oggetti semplici, array o raccolte semplici.
For abstract auto property, indexer, or event declarations.
// 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};
}
}
}
Inserire una riga vuota:
Dopo una lista di istruzioni
using.Tra dichiarazioni di metodi, proprietà e tipi interni.
Alla fine di ogni file.
Le dichiarazioni di campi e costanti si possono raggruppare in base alla pertinenza. In tal caso, si consiglia di inserire una riga vuota tra i gruppi per facilitarne la lettura.
Evitare di inserire una riga vuota:
Dopo
{, la parentesi graffa di apertura.Prima
}, la parentesi graffa di chiusura.Dopo un blocco di commenti, o un commento di una sola riga.
Adiacente a un'altra riga vuota.
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()
{
}
}
Utilizzo degli spazi
Inserire uno spazio:
Attorno un operatore binario e ternario.
Tra una parentesi aperta e le parole chiave
if,for,foreach,catch,while,lockousing.Prima e all'interno di un blocco accessor di una sola riga.
Tra gli accessori in un blocco accessor di una sola riga.
Dopo una virgola che non si trova alla fine di una riga.
Dopo un punto e virgola in un istruzione
for.Dopo i due punti in un'istruzione
casedi una sola riga.Intorno ai due punti in una dichiarazione di tipo.
Intorno a una freccia lambda.
Dopo un simbolo di commento su una sola riga (
//), e prima di esso se utilizzato alla fine di una riga.Dopo la parentesi graffa di apertura e prima di quella di chiusura in un inizializzatore di una sola riga.
Non usare uno spazio:
Dopo le parentesi di conversione di tipo.
L'esempio seguente mostra un uso adeguato degli spazi, secondo alcune delle convenzioni sopra menzionate:
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 };
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.
}
}
Convenzioni di denominazione
Utilizzare il PascalCase per tutti gli spazi dei nomi, i nomi dei tipi e gli identificatori di livello membro (ovvero metodi, proprietà, costanti, eventi), tranne per i campi privati:
namespace ExampleProject
{
public class PlayerCharacter
{
public const float DefaultSpeed = 10f;
public float CurrentSpeed { get; set; }
protected int HitPoints;
private void CalculateWeaponDamage()
{
}
}
}
Utilizzare il camelCase per tutti gli altri identificatori (ad esempio variabili locali, argomenti dei metodi) e utilizzare un trattino basso (_) come prefisso per i campi privati (ma non per metodi o proprietà, come spiegato sopra):
private Vector3 _aimingAt; // Use an `_` prefix for private fields.
private void Attack(float attackStrength)
{
Enemy targetFound = FindTarget(_aimingAt);
targetFound?.Hit(attackStrength);
}
Esiste un'eccezione per gli acronimi composti da due lettere, come UI, che si dovrebbero scrivere in maiuscolo dove ci si aspetterebbe il PascalCase, altrimenti in minuscolo.
Si noti che id non è un acronimo, quindi si dovrebbe trattare come un identificatore normale:
public string Id { get; }
public UIManager UI
{
get { return uiManager; }
}
In genere, è sconsigliato utilizzare il nome di un tipo come prefisso di un identificatore, come ad esempio string strText o float fPower. Un'eccezione è tuttavia fatta per le interfacce, che dovrebbero, in effetti, avere una lettera maiuscola I come prefisso ai loro nomi, come IInventoryHolder o IDamageable.
Infine, considerare di scegliere nomi descrittivi e non cercare di accorciarli troppo se ciò ne compromette la leggibilità.
Ad esempio, se si desidera scrivere codice per trovare un nemico vicino e colpirlo con un'arma, è preferito:
FindNearbyEnemy()?.Damage(weaponDamage);
Piuttosto che:
FindNode()?.Change(wpnDmg);
Variabili membro
Non dichiarare variabili membro se sono utilizzate solo localmente in un metodo, poiché ciò rende il codice più difficile da seguire. Dichiarale invece come variabili locali nel corpo del metodo.
Variabili locali
Dichiara le variabili locali il più vicino possibile al loro primo utilizzo. Questo rende più facile seguire il codice, senza dover scorrere troppo per trovare il punto in cui viene dichiarata la variabile.
Variabili locali tipizzate implicitamente
Si consideri l'utilizzo della tipizzazione implicita (var) per dichiarare una variabile locale, ma si consiglia di farlo solo quando il tipo è evidente dal lato destro dell'assegnazione:
// 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;
Altre considerazioni
Utilizzare modificatori di accesso espliciti.
Utilizzare le proprietà anziché i campi non privati.
Utilizzare i modificatori in questo ordine:
public/protected/private/internal/virtual/override/abstract/new/static/readonly.Evitare di utilizzare nomi completamente qualificati o il prefisso
this.per i membri quando non è necessario.Rimuovere le istruzioni
usingnon utilizzate e le parentesi non necessarie.Considerare di omettere il valore iniziale predefinito per un tipo.
Considera di utilizzare operatori null-conditional o type initializer per rendere il codice più compatto.
Utilizzare il cast sicuro quando c'è la possibilità che il valore sia di tipo diverso, altrimenti utilizzare il cast diretto.