Classes statiques et membres de classe statique (Guide de programmation C#)

Une classe statique est essentiellement identique à une classe non statique, à une différence près : une classe statique ne peut pas être instanciée. En d’autres termes, vous ne pouvez pas utiliser l’opérateur new pour créer une variable du type de classe. Du fait qu’il n’existe aucune variable d’instance, vous accédez aux membres d’une classe statique en utilisant le nom de classe lui-même. Par exemple, si vous avez une classe statique nommée UtilityClass qui a une méthode statique publique nommée MethodA, vous appelez la méthode comme illustré dans l’exemple suivant :

UtilityClass.MethodA();

Une classe statique peut servir de conteneur pratique pour des ensembles de méthodes qui fonctionnent simplement sur des paramètres d’entrée et n’ont pas à obtenir ou définir de champs d’instance internes. Par exemple, dans la bibliothèque de classes .NET, la classe System.Math statique contient des méthodes qui effectuent des opérations mathématiques, sans qu’il soit nécessaire de stocker ou de récupérer des données spécifiques à une instance particulière de la classe Math. Autrement dit, vous appliquez les membres de la classe en spécifiant le nom de la classe et le nom de la méthode, comme illustré dans l’exemple suivant.

double dub = -3.14;
Console.WriteLine(Math.Abs(dub));
Console.WriteLine(Math.Floor(dub));
Console.WriteLine(Math.Round(Math.Abs(dub)));

// Output:
// 3.14
// -4
// 3

Comme c’est le cas pour tous les types de classe, le runtime .NET charge les informations de type d’une classe statique lorsque le programme faisant référence à la classe est chargé. Le programme ne peut pas spécifier exactement le moment où la classe est chargée. Toutefois, son chargement est garanti, ses champs sont initialisés et son constructeur statique est appelé avant le premier référencement de la classe dans votre programme. Un constructeur statique est appelé une seule fois et une classe statique reste en mémoire pendant la durée de vie du domaine d’application dans lequel votre programme réside.

Notes

Pour créer une classe non statique permettant la création d’une seule instance d’elle-même, consultez Implémentation d’un singleton en C#.

La liste suivante fournit les fonctionnalités principales d’une classe statique :

  • Elle contient uniquement des membres statiques.

  • Elle ne peut pas être instanciée.

  • Elle est verrouillée (sealed).

  • Elle ne peut pas contenir de Constructeurs d’instances.

La création d’une classe statique est par conséquent très semblable à la création d’une classe contenant uniquement des membres statiques et un constructeur privé. Un constructeur privé empêche la classe d’être instanciée. L’avantage de l’utilisation d’une classe statique est que le compilateur peut vérifier qu’aucun membre d’instance n’a été ajouté par erreur. Le compilateur veille à ce que les instances de cette classe ne puissent pas être créées.

Les classes statiques sont sealed et ne peuvent par conséquent pas être héritées. Elles ne peuvent hériter d’aucune classe ou interface, à l’exception de Object. Les classes statiques ne peuvent pas contenir de constructeur d’instance. Toutefois, elles peuvent contenir un constructeur statique. Les classes non statiques doivent également définir un constructeur statique si la classe contient des membres statiques qui requièrent une initialisation non triviale. Pour plus d’informations, consultez Constructeurs statiques.

Exemple

Voici un exemple de classe statique qui contient deux méthodes qui convertissent la température des degrés Celsius en degrés Fahrenheit et des degrés Fahrenheit en degrés Celsius :

public static class TemperatureConverter
{
    public static double CelsiusToFahrenheit(string temperatureCelsius)
    {
        // Convert argument to double for calculations.
        double celsius = Double.Parse(temperatureCelsius);

        // Convert Celsius to Fahrenheit.
        double fahrenheit = (celsius * 9 / 5) + 32;

        return fahrenheit;
    }

    public static double FahrenheitToCelsius(string temperatureFahrenheit)
    {
        // Convert argument to double for calculations.
        double fahrenheit = Double.Parse(temperatureFahrenheit);

        // Convert Fahrenheit to Celsius.
        double celsius = (fahrenheit - 32) * 5 / 9;

        return celsius;
    }
}

class TestTemperatureConverter
{
    static void Main()
    {
        Console.WriteLine("Please select the convertor direction");
        Console.WriteLine("1. From Celsius to Fahrenheit.");
        Console.WriteLine("2. From Fahrenheit to Celsius.");
        Console.Write(":");

        string? selection = Console.ReadLine();
        double F, C = 0;

        switch (selection)
        {
            case "1":
                Console.Write("Please enter the Celsius temperature: ");
                F = TemperatureConverter.CelsiusToFahrenheit(Console.ReadLine() ?? "0");
                Console.WriteLine("Temperature in Fahrenheit: {0:F2}", F);
                break;

            case "2":
                Console.Write("Please enter the Fahrenheit temperature: ");
                C = TemperatureConverter.FahrenheitToCelsius(Console.ReadLine() ?? "0");
                Console.WriteLine("Temperature in Celsius: {0:F2}", C);
                break;

            default:
                Console.WriteLine("Please select a convertor.");
                break;
        }

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Example Output:
    Please select the convertor direction
    1. From Celsius to Fahrenheit.
    2. From Fahrenheit to Celsius.
    :2
    Please enter the Fahrenheit temperature: 20
    Temperature in Celsius: -6.67
    Press any key to exit.
 */

Membres static

Une classe non statique peut contenir des méthodes, des champs, des propriétés ou des événements statiques. Le membre statique peut être appelé sur une classe, même en cas d’inexistence d’une instance de la classe. Le membre statique est toujours accessible par le nom de la classe, et non par le nom de l’instance. Une seule copie d’un membre statique existe, quel que soit le nombre d’instances de la classe qui ont été créées. Les méthodes et propriétés statiques ne peuvent pas accéder à des champs ou des événements non statiques dans leur type contenant. Elles ne peuvent pas non plus accéder à une variable d’instance d’un objet quelconque à moins qu’elles soient passées explicitement dans un paramètre de méthode.

Il est plus courant de déclarer une classe non statique avec certains membres statiques que de déclarer une classe entière comme étant statique. Deux utilisations courantes des champs statiques consistent à conserver un décompte du nombre d’objets qui sont instanciés ou à stocker une valeur qui doit être partagée entre toutes les instances.

Les méthodes statiques peuvent être surchargées mais pas substituées, car elles appartiennent à la classe et non pas à une instance de la classe.

Bien qu’un champ ne puisse pas être déclaré comme static const, un champ const est essentiellement statique dans son comportement. Il appartient au type, pas aux instances du type. Par conséquent, les champs const sont accessibles en utilisant la même notation ClassName.MemberName utilisée pour les champs statiques. Aucune instance d’objet n’est requise.

C# ne prend pas en charge les variables locales statiques (c’est-à-dire, les variables déclarées dans la portée de la méthode).

Vous déclarez des membres de classe statique en utilisant le mot clé static avant le type de retour du membre, comme illustré dans l’exemple suivant :

public class Automobile
{
    public static int NumberOfWheels = 4;

    public static int SizeOfGasTank
    {
        get
        {
            return 15;
        }
    }

    public static void Drive() { }

    public static event EventType? RunOutOfGas;

    // Other non-static fields and properties...
}

Les membres statiques sont initialisés avant le premier accès au membre statique et avant que le constructeur statique, s’il en existe un, soit appelé. Pour accéder à un membre de classe statique, utilisez le nom de la classe au lieu d’un nom de variable pour spécifier l’emplacement du membre, comme illustré dans l’exemple suivant :

Automobile.Drive();
int i = Automobile.NumberOfWheels;

Si votre classe contient des champs statiques, fournissez un constructeur statique qui les initialise quand la classe est chargée.

Un appel à une méthode statique génère une instruction d’appel en langage CIL (Common Intermediate Language), alors qu’un appel à une méthode d’instance génère une instruction callvirt, qui vérifie également l’existence de références d’objet null. Toutefois, la différence de performances entre les deux n’est pas significatif.

Spécification du langage C#

Pour plus d’informations, voir Classes statiques, Membres statiques et d’instance et Constructeurs statiques dans la spécification du langage C#. La spécification du langage est la source de référence pour la syntaxe C# et son utilisation.

Voir aussi