Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Guia de Estilo C#

Ter convenções de codificação bem definidas e consistentes é importante para todos os projetos, e o Godot não é uma exceção a essa regra.

Esta página contém um guia de estilo de codificação que é seguido por desenvolvedores e colaboradores do próprio Godot. Como tal, destina-se principalmente àqueles que querem contribuir com o projeto, mas como as convenções e diretrizes mencionadas neste artigo são as mais amplamente adotadas pelos usuários da linguagem, nós o encorajamos a fazer o mesmo, especialmente se você ainda não tem um guia ainda.

Nota

Este artigo não é de forma alguma um guia completo sobre como seguir as convenções de codificação padrão ou as práticas recomendadas. Se você não tiver certeza de um aspecto que não é abordado aqui, consulte a documentação mais abrangente, como C# Coding Conventions ou Framework Design Guidelines.

Especificação de Linguagem

Atualmente, o Godot usa o C# versão 7.0 em seu mecanismo e código-fonte de exemplo. Portanto, antes de passarmos para uma versão mais recente, é preciso ter cuidado para não misturar os recursos da linguagem disponíveis apenas no C# 7.1 ou posterior.

Para obter informações detalhadas sobre as funcionalidades do C# em diferentes versões, consulte Novidades no C#.

Formatação

Orientações gerais

  • Use caracteres de pular linha (LF) para quebrar linhas, não CRLF ou CR.

  • Use um caractere de alimentação de linha no final de cada arquivo, exceto para arquivos csproj.

  • Use a codificação UTF-8 sem uma marca de ordem de byte <https://pt.wikipedia.org/wiki/Marca_de_ordem_de_byte>.

  • Use 4 espaços em vez de tabs para indentação (que é referido como "tabs suaves").

  • Considere quebrar uma linha em várias se for mais de 100 caracteres.

Quebras de linha e linhas em branco

Para uma regra geral de recuo, siga o "estilo Allman" que recomenda colocar a chave associada a uma declaração de controle na próxima linha, recuada para a mesmo nível:

// Use this style:
if (x > 0)
{
    DoSomething();
}

// NOT this:
if (x > 0) {
    DoSomething();
}

No entanto, você pode optar por omitir quebras de linha dentro de chaves:

  • Para simples propriedades acessoras.

  • Para inicializadores de simples objeto, array ou coleção.

  • Para auto propriedade abstrata, indexador ou declarações de evento.

// 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};
        }
    }
}

Insira uma linha em branco:

  • Depois de uma lista de declarações using.

  • Entre o método, propriedades e declarações de tipo interno.

  • No final de cada arquivo.

Declarações de campos e constantes podem ser agrupadas de acordo com a relevância. Nesse caso, considere inserir uma linha em branco entre os grupos para facilitar a leitura.

Evite inserir uma linha em branco:

  • Depois``{``, a chave de abertura.

  • Antes }, a chave de fechamento.

  • Após um bloco de comentário ou um comentário de uma única linha.

  • Adjacente a outra linha em branco.

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()
    {
    }
}

Usando espaços

Insira um espaço:

  • Around a binary and ternary operator.

  • Entre um parêntese de abertura e as palavras-chave if, for, foreach, catch, while, lock ou using.

  • Antes e dentro de um bloco de acessador de linha única.

  • Entre os acessadores em um bloco de acessador de linha única.

  • Depois de uma vírgula que não está no fim de uma linha.

  • Depois de um ponto-e-vírgula em uma declaração``for``.

  • Depois de dois pontos em declaração case de linha única.

  • Em torno de dois pontos em uma declaração de tipo.

  • Em torno de uma seta lambda.

  • Após um símbolo de comentário de linha única (//), e antes se usado no final de uma linha.

Não use um espaço:

  • Depois de um parênteses de um tipo de conversão.

  • Dentro de chaves de inicialização de linha única.

O exemplo a seguir mostra um uso adequado dos espaços, de acordo com algumas das convenções mencionadas acima:

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.
    }
}

Convenções de nomes

Use PascalCase para todos os namespaces, nomes de tipos e identificadores de nível de membro (ou seja, métodos, propriedades, constantes, eventos), exceto para campos privados:

namespace ExampleProject
{
    public class PlayerCharacter
    {
        public const float DefaultSpeed = 10f;

        public float CurrentSpeed { get; set; }

        protected int HitPoints;

        private void CalculateWeaponDamage()
        {
        }
    }
}

Use camelCase para todos os outros identificadores (isto é, variáveis locais, argumentos de método) e use sublinhado (_) como um prefixo para campos privados (mas não para métodos ou propriedades, como explicado acima):

private Vector3 _aimingAt; // Use a `_` prefix for private fields.

private void Attack(float attackStrength)
{
    Enemy targetFound = FindTarget(_aimingAt);

    targetFound?.Hit(attackStrength);
}

Há uma exceção com siglas que consistem em duas letras como UI, que devem ser escritas em letras maiúsculas quando usadas onde o PascalCase seria esperado, e em letras minúsculas, caso contrário.

Note que id não é um acrônimo, então deve ser tratado como um identificador normal:

public string Id { get; }

public UIManager UI
{
    get { return uiManager; }
}

Geralmente é desencorajado usar um nome de tipo como um prefixo de um identificador como string strText ou float fPower, por exemplo. No entanto, há uma exceção sobre interfaces, caso em que elas devem ser nomeadas usando maiúsculas I como um prefixo, como IInventoryHolder ou IDamageable.

Por último, considere a escolha de nomes descritivos e não tente encurtá-los demais se isso afetar a legibilidade.

Por exemplo, se você quiser escrever um código para encontrar um inimigo próximo e acertar com uma arma, prefira:

FindNearbyEnemy()?.Damage(weaponDamage);

Ao invés de:

FindNode()?.Change(wpnDmg);

Variáveis de membro

Não declare variáveis de membro se elas forem usadas apenas localmente em um método, pois torna o código mais difícil de seguir. Em vez disso, declare-as como variáveis locais no corpo do método.

Variáveis locais

Declare variáveis locais o mais pŕoximo possível de seu primeiro uso. Isto torna mais fácil seguir o código, sem ter que rolar muito para encontrar onde a variável foi declarada.

Variáveis locais de tipo implícito

Considere usar implicitamente a digitação (var) para declaração de uma variável local, mas faça isso somente quando o tipo for evidente do lado direito da atribuição:

// 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;

Outras considerações

  • Use modificadores de acesso explícito.

  • Use propriedades em vez de campos não privados.

  • Use modificadores nesta ordem: public/protected/private/internal/virtual/override/abstract/`` new``/static/readonly.

  • Evite usar nomes completos ou o prefixo this. para membros, quando não for necessário.

  • Remova as instruções using não utilizadas e parênteses desnecessários.

  • Considere omitir o valor inicial padrão de um tipo.

  • Considere usar operadores condicionais nulos ou digite inicializadores para tornar o código mais compacto.

  • Use uma conversão segura quando houver a possibilidade de o valor ser um tipo diferente e use a conversão direta caso contrário.