C# Guideline

Les guidelines présentées dans ce document suivent les recommandations faites par Microsoft.
Les guidelines Microsoft sont disponibles sur MSDN: Framework Design Guidelines.

Formatting Rules

Programming

Programmez en anglais.

Indentation

Utilisez une indentation de 4 espaces.
N'utilisez pas de tabulations.
Indentez votre code.

Layout

Utilisez la syntaxe expanded.
*Exception, la syntaxe collapsed est autorisée lorsque qu'il n'y a qu'une seule instruction par bloc.

namespace Company.Product
{
    public class ClassName
    {
        public int Property { get; set; }

        public void DoMethod (int parameter)
        {
            if(true)
            {
                // Insert code here.    
            }
        }
    }
}

Ecrivez une seule déclaration par ligne.
Ecrivez une seule instruction par ligne.

public class ClassName
{
    private int index, count;

    public void DoMethod ()
    {
        index = count = 0;
    }
}

Ajoutez au moins une ligne vide entre les définitions de méthodes et les définitions de propriétés.

Utilisez des parenthèses pour les clauses conditionnelles.

if ((val1 > val2) && (val1 > val3))
{
    // ...
}

Comments

Ajoutez un espace entre le délimiteur de commentaire et le texte du commentaire.

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

Documentez le code à l'aide des commentaires de documentation XML.

public class TestClass
{
    /// <summary>DoWork is a method in the TestClass class.
    /// <para>Here's how you could make a second paragraph in a description. <see cref="System.Console.WriteLine(System.String)" /> for information about output statements.</para>
    /// <seealso cref="TestClass.Main" />
    /// </summary>
    /// <param name="integerNumber">Used to indicate status.</param>
    /// <param name="decimalNumber">Used to specify context.</param>
    public static void DoWork(int integerNumber, float decimalNumber)
    {
    }
    static void Main()
    {
    }
}

Case

Il y a 2 syntaxe de casses utilisées:

  • Pascal Case: applique une majuscule au premier caractère de chaque mot (y compris les acronymes).
    PropertyDescriptor
    IOStream
  • Camel Case: applique une majuscule au premier caractère de chaque mot excepté pour le premier mot.
    value
    aField

Évitez que les noms des identifiants diffèrent uniquement par leur casse.

Evitez ces erreurs fréquentes !

Pascal case Camel case Erreur fréquente
Id
id
ID
Ok
ok
OK
Database
database
DataBase
Hashtable
hashtable
HashTable
Callback
callback
CallBack
Placeholder
placeholder
PlaceHolder
Metadata
metadata
MetaData
UserName
userName
Username
FileName
fileName
Filename
Endpoint
endpoint
EndPoint
Email
email
EMail

Names of Identifiers

Identifiant Case Exemple
Namespace Pascal
namespace System.Security 
{ 
    // Insert code here.
}
Class Pascal
public class StreamReader 
{
    // Insert code here. 
}
Interface Pascal
public interface IEnumerable 
{
    // Insert code here. 
}
Method Pascal
public class Object 
{
    public virtual string ToString();
}
Property Pascal
public class String 
{
    public int Length { get; }
}
Event Pascal
public class Process 
{
    public event EventHandler Exited;
}
Field Pascal
public class MessageQueue 
{
    public static readonly TimeSpan InfiniteTimeout;

    public struct UInt32 
    {
        public const Min = 0;
    }
}
Enum type Pascal
public enum FillMode 
{
    // Insert code here.
}
Enum value Pascal
public enum FillMode 
{
    Append,
    Insert,
    Prepend
}
Parameter Camel
public class Convert 
{
    public static int ToInt32(string value);
}
Local variable Camel
public static class Math 
{
    public static int Multiply(int multiplicand, int multiplicator) 
    {
        int product = multiplicand * multiplicator;
        return product;
    }
}

Names of Solutions

Nommez vos solutions en Pascal case conformément à la règle suivante:

<Company>.<Product>
// Recommended
Actiris.Jobs
Actiris.MonActiris

Names of Projects

Nommez vos projets en Pascal case conformément à la règle suivante:

<Company>.(<Product>|<Technology>)[.<Feature>]
// Recommended

// Framework examples
Actiris.Jobs.Model
Actiris.Jobs.Data
Actiris.Jobs.Service

// Product examples
Actiris.MonActiris.Model
Actiris.MonActiris.Data
Actiris.MonActiris.Service
Actiris.MonActiris.Web.AspNetCore
Actiris.MonActiris.Web.AspNet
Actiris.MonActiris.Windows.Universal
Actiris.MonActiris.Xamarin.IPhone
Actiris.MonActiris.Xamarin.Android

Names of Namespaces

Nommez vos espaces de noms conformément à la règle suivante:

<Company>.(<Product>|<Technology>)[.<Feature>][.<Subnamespace>]
// Recommended

// Framework examples
Actiris.Security
Actiris.IO.Pdf
Actiris.IO.Excel
Actiris.Web.TagHelpers

// Product examples
Actiris.MonActiris.Web.Controllers
Actiris.MonActiris.Web.ViewModels

N'utilisez pas le nom d'un namespace comme nom d'un type au sein du namespace.

// Not Recommended
namespace Actiris.MonActiris.Debug
{
    public class Debug 
    {
    }
}

Names of Assemblies

Choisissez un nom d'assembly suggérant un ensemble de fonctionnalités, tel que System.Data.
Nommez vos assemblies pour qu'ils correspondent au namespace.

// Recommended
Actiris.Controls.Calendar
Actiris.Controls.DataGrid

Names of DLLs

Nommez vos DLLs conformément à la règle suivante:

<Company>.<Component>.dll
Actiris.Controls.dll

Names of Classes

Utilisez un nom ou un groupe nominal pour nommer vos classes.

// Recommended
public class Employee {...}
public class Job {...}
public class Document {...}

Ajoutez à la fin du nom d'une classe dérivée le nom de la classe de base si cela est pertinent.

// Recommended
public class ArgumentOutOfRangeException {...}
public class SerializableAttribute {...}

Names of Interfaces

Préfixez les interfaces avec la lettre "I". Utilisez un adjectif, nom ou un group nominale pour nommer vos interfaces.

// Recommended
public interface IComponent {...}
public interface ICustomAttributeProvider {...}
public interface IPersistable {...}

Names of Structs

Utilisez un nom ou un groupe nominal pour nommer vos structures.

// Recommended
public struct Coordinates {...}

Names of Enums

Utilisez un nom singulier pour nommer vos enums.

// Recommended
public enum LogLevel {...}
public enum ServerStatus {...}
public enum ModelState {...}
public enum JobType {...}

N'ajoutez pas un suffixe Enum, Flag(s) à vos enums.

// Not Recommended
public enum TypeEnum {...}
public enum StatusFlags {...}

Names of Methods

Utilisez un verbe ou une locution verbale pour nommer vos méthodes.

// Recommended
public class String
{
    public int CompareTo(...) { ... }
    public string[] Split(...) { ... }
    public string Trim() { ... }
}

Names of Properties

Utilisez un nom, un groupe nominale ou un adjectif pour nommer vos propriétés.

// Recommended
public class Galaxy
{
    public string Name { get; set; }
    public int MegaLightYears { get; set; }
}

Utilisez le pluriel pour nommer une propriété de type collection. N'ajoutez pas de suffixe "List" ou "Collection" à une propriété de type collection.

// Not Recommended
public class Universe
{
    public List<Galaxy> GalaxyList { get; set; }
}
// Recommended
public class Universe
{
    public List<Galaxy> Galaxies { get; set; }
}

Utilisez un nom affirmatif pour nommer vos propriétés de type Boolean. Ajoutez le suffixe "Is", "Has", "Can" à une propriété de type Boolean si cela est pertinent.

// Recommended
public class Planet
{
    public bool HasWater { get; set; }
    public bool IsClassified { get; set; }
    public bool CanSupportLife { get; set; }
}

Names of Events

Utilisez un verbe ou une locution verbale pour nommer vos événements.

Clicked
Painting
DroppedDown

N'ajoutez pas le préfixe ou le suffixe "Before", "After" pour indiquer la chronologie d'un événement. Privilégiez l'utilisation du temps présent ou passé.
Exemple: Pour un événement de fermeture d'une fenêtre, si l'événement est déclenché avant que la fenetre soit fermée nommez votre événement Closing. Mais si votre événement est déclenché après que la fenêtre soit fermée, nommez votre événement Closed.

// Not Recommended
public class CustomClass
{
    public event EventHandler BeforeClose;
    public event EventHandler AfterClose;
}
// Recommended
public class CustomClass
{
    public event EventHandler Closing;
    public event EventHandler Closed;
}

Nommez vos events handlers (delegates utilisées comme type d'événements) avec le suffixe "EventHandler". Utilisez 2 paramètres nommé sender et e dans un event handler.

// Recommended
public delegate void ClickedEventHandler(object sender, ClickedEventArgs e);

Utilisez le suffixe "EventArgs" pour les classes de type event argument.

// Recommended
public class CustomEventArgs : EventArgs {...}

Names of Fields

Utilisez un nom, un groupe nominal ou un adjectif pour nommer vos champs.
Utilisez le Pascal case pour nommer un champ "public" ou "protected".

Names of Parameters

Utilisez le Camel case pour nommer vos paramètres.
Utilisez des noms de paramètres explicites et claires.

// Not Recommended
public class Utilities
{
    public int ConvertHoursToSeconds(int h, int m, int s) {...}
}
// Recommended
public class Utilities
{
    public int ConvertHoursToSeconds(int hours, int minutes, int seconds) {...}
}

Names of Resources

Utilisez le Pascal case pour nommer les clées de ressources.
Utilisez des noms de ressources explicites et claires.
N'utilisez pas de caractères spéciaux, utilisez uniquement des caractères alphanumériques et des underscores.
Utilisez le point "." comme séparateur entre objet et propriété.

EditJob
SaveJobEditing
CancelJobEditing
ActirisLogo.Source
ActirisLogo.AlternateText

Style Rules

General Coding Conventions

Programmez en anglais.

File Conventions

Évitez d'ajouter plus d'une classe par fichier.
Le nom du fichier doit correspondre avec la nom de la classe qu'il contient.

Code Conventions

Évitez d'avoir plus de 500 lignes de code par fichier.
Évitez d'avoir plus de 30 lignes de code par méthode.
Exception: cette limite ne s'applique pas aux fichiers auto-générés.

Évitez d'utilisez plus de 5 arguments par méthodes. Dans le cas contraire, utilisez une classe ou une structure pour passer de multiples arguments.

Exception Conventions

Ne traitez pas les erreurs en capturant des exceptions non-spécifiques tel que System.Exception ou System.SystemException.

// Not Recommended
public class ExceptionHandlingExample
{
    public void DoWork()
    {
        // Do some work that might throw exceptions.
    }

    public void MethodWithBadHandler()
    {
        try
        {
            DoWork();
        }
        catch (Exception e)
        {
            // Handle the exception and continue executing.
        }
    }
}

Ne soulevez pas d'exceptions de type System.Exception ou System.SystemException.

// Not Recommended
public void DoWork()
{
    if(true)
    {
        throw new Exception();
    }
}
Utilisez un throw vide lorsque vous repropagez l'exception afin de préserver la pile d'appel.
// Not Recommended
public void DoWork()
{
    try
    {
        // Try to access a resource.
    }
    catch (System.UnauthorizedAccessException e)
    {
        LogError(e);
        throw e;     
    }
}
// Recommended
public void DoWork()
{
    try
    {
        // Try to access a resource.
    }
    catch (System.UnauthorizedAccessException e)
    {
        LogError(e);
        throw;     
    }
}

Using Directive Conventions

Privilégiez l'import des namespaces à l'utilisation des fully qualified object names.
En d'autres mots, n'utilisez les fully qualified object names que si il y a un conflit de noms d'objets.

// Not Recommended
using System;

namespace Demo
{
    public class Sample
    {
        private System.Collections.Generic.List<string> names = new System.Collections.Generic.List<string>();
    }
}
// Recommended
using System;
using System.Collections.Generic;

namespace Demo
{
    public class Sample
    {
        private List<string> names = new List<string>();
    }
}

Encapsulation Conventions

Ne délcarez pas des champs de classe public ou protected.

Un champ de classe ne devrait jamais être public ou protected. Dans le cas où vous voulez accéder au champ, privilégiez l'utilisation des propriétés.

Type Conventions

Privilégiez les types prédéfinis du langage C# et non les alias du namespace System.

// Not Recommended
Object data;
String name;
Int32 id;
// Recommended
object data;
string name;
int id;

Implicitly Typed Local Variables

Utilisez uniquement le typage implicite pour les variables locales lorsque le type de la variable est évident ou lorsque le type n'est pas important.

// Not Recommended
// When the type of a variable is not clear from the context, use an explicit type.
int total = ExampleClass.ResultSoFar();
// Recommended
// When the type of a variable is clear from the context, use var in the declaration.
var hello = "Hello World!";
var amount = 42;
var number = Convert.ToInt32(Console.ReadLine());

Index Conventions

Utilisez toujours un indexe basé sur zéro pour les arrays.
Utilisez toujours un indexe basé sur zéro pour les collections indexées.

General Naming Conventions

Choisisez un nom d'identifiant compréhensible, clair et conforme à l'anglais.

// Not Recommended
public int AlignmentHorizontal { get; set; }
// Recommended
public int HorizontalAlignment  { get; set; }

Privilégiez la lisibilité à la brieveté.
N'utilisez pas d'abbréviation. Ne tronquez pas une partie du nom d'un identifiant.
Exception: Le nom d'une variable utilisée pour itérer dans une boucle peut être abrégé.
Évitez les acronymes excepté s'ils sont communément admis.

// Not Recommended
public bool ScrollableX { get; set; }
public int NatNum { get; set; }
public int T { get; set; }
// Recommended
public bool CanScrollHorizontally  { get; set; }
public int NationalNumber { get; set; }
public int Temp { get; set; }
for (int i = 0; i < 10; i++) 
{
    // Insert code here.
}

N'utilisez pas d'underscore, trait d'unions ou de caractère spéciaux.

// Not Recommended
public class Student
{
    private string student_name;
    private int student-age;
    private string nomÉcole;
}

N'utilisez pas la notation hongroise c'est-à-dire ne préfixez pas les variables par leur type.

// Not Recommended
public class Student
{
    private string sName;
    private int iAge;
    private List<Course> lCourse;
    static int s_iStudentsNumber;
}

Evitez d'utiliser des mots réservés propre au language de programmation.

// Not Recommended
public class Student
{
    private string @class;
}

General Comment Conventions

Commentez le code lorsque cela est nécessaire.
Evitez d'ajouter des commentaires pour expliquer ce qui est évident. Le code devrait être suffisament clair pour être compris de par lui même.
Toutefois, utilisez les commentaires pour expliquer le code; lorsque celui-ci est complexe ou lorsque qu'une correction a dû être apportée.

Documentez le code à l'aide des commentaires de documentation XML.
Utilisez la documentation Xml pour fournir aux utilisateurs les informations dont ils ont besoin de savoir sur le comportement général du code.
N'utilisez pas la documentation Xml pour préciser des détails sur l'implémentation du code.
Dans le cas d'une API, documentez chaque méthode.