Instructions de déclaration

Une instruction de déclaration déclare une nouvelle variable locale, constante locale ou variable de référence locale. Pour déclarer une variable locale, spécifiez son type et indiquez son nom. Vous pouvez déclarer plusieurs variables du même type dans une même instruction, comme le montre l’exemple suivant :

string greeting;
int a, b, c;
List<double> xs;

Dans une instruction de déclaration, vous pouvez également initialiser une variable avec sa valeur initiale :

string greeting = "Hello";
int a = 3, b = 2, c = a + b;
List<double> xs = new();

Les exemples précédents spécifient explicitement le type d’une variable. Vous pouvez également laisser le compilateur déduire le type d’une variable à partir de son expression d’initialisation. Pour ce faire, utilisez le mot clé var au lieu du nom d’un type. Pour plus d’informations, consultez la section Variables locales implicitement typées.

Pour déclarer une constante locale, utilisez le const mot clé, comme le montre l’exemple suivant :

const string Greeting = "Hello";
const double MinLimit = -10.0, MaxLimit = -MinLimit;

Lorsque vous déclarez une constante locale, vous devez également l’initialiser.

Pour plus d’informations sur les variables de référence locales, consultez la section Variables de référence.

Variables locales implicitement typées

Lorsque vous déclarez une variable locale, vous pouvez laisser le compilateur déduire le type de la variable à partir de l’expression d’initialisation. Pour ce faire, utilisez le mot clé var au lieu du nom d’un type :

var greeting = "Hello";
Console.WriteLine(greeting.GetType());  // output: System.String

var a = 32;
Console.WriteLine(a.GetType());  // output: System.Int32

var xs = new List<double>();
Console.WriteLine(xs.GetType());  // output: System.Collections.Generic.List`1[System.Double]

Comme le montre l’exemple précédent, les variables locales implicitement typées sont fortement typées.

Notes

Lorsque vous utilisez var dans le contexte pouvant accepter la valeur Null activé et que le type d’une expression d’initialisation est un type référence, le compilateur déduit toujours un type de référence pouvant accepter la valeur Null même si le type d’une expression d’initialisation n’est pas compatible avec la valeur Null.

Une utilisation courante de var est l’expression d’invocation d’un constructeur. L’utilisation de var vous évite de répéter un nom de type dans une déclaration de variable et une instanciation d’objet, comme le montre l’exemple suivant :

var xs = new List<int>();

Vous pouvez utiliser une expression new typée cible en guise d’alternative :

List<int> xs = new();
List<int>? ys = new();

Lorsque vous utilisez des types anonymes, vous devez utiliser des variables locales implicitement typées. L’exemple suivant montre une expression de requête qui utilise un type anonyme pour contenir le nom et le numéro de téléphone d’un client :

var fromPhoenix = from cust in customers
                  where cust.City == "Phoenix"
                  select new { cust.Name, cust.Phone };

foreach (var customer in fromPhoenix)
{
    Console.WriteLine($"Name={customer.Name}, Phone={customer.Phone}");
}

Dans l’exemple précédent, vous ne pouvez pas spécifier explicitement le type de la variable fromPhoenix. Le type est IEnumerable<T>, mais, dans ce cas, T est un type anonyme et vous ne pouvez pas fournir son nom. C’est pourquoi vous devez utiliser var. Pour la même raison, vous devez utiliser var lorsque vous déclarez la variable d’itération customer dans l’instruction foreach.

Pour plus d’informations sur les variables locales implicitement typées, consultez Variables locales implicitement typées.

Dans les critères spéciaux, le mot clé var est utilisé dans un modèle var.

Variables de référence

Lorsque vous déclarez une variable locale et que vous ajoutez le mot clé ref avant le type de la variable, vous déclarez une variable de référence, ou une variable locale ref :

ref int aliasOfvariable = ref variable;

Une variable de référence est une variable qui fait référence à une autre variable, appelée « référent ». Autrement dit, une variable de référence est un alias à son référent. Lorsque vous affectez une valeur à une variable de référence, cette valeur est assignée au référent. Lorsque vous lisez la valeur d’une variable de référence, la valeur du référent est retournée. L’exemple suivant illustre ce comportement :

int a = 1;
ref int aliasOfa = ref a;
Console.WriteLine($"(a, aliasOfa) is ({a}, {aliasOfa})");  // output: (a, aliasOfa) is (1, 1)

a = 2;
Console.WriteLine($"(a, aliasOfa) is ({a}, {aliasOfa})");  // output: (a, aliasOfa) is (2, 2)

aliasOfa = 3;
Console.WriteLine($"(a, aliasOfa) is ({a}, {aliasOfa})");  // output: (a, aliasOfa) is (3, 3)

Utilisez l’opérateur d’assignation ref= ref pour changer le référent d’une variable de référence, comme le montre l’exemple suivant :

void Display(int[] s) => Console.WriteLine(string.Join(" ", s));

int[] xs = [0, 0, 0];
Display(xs);

ref int element = ref xs[0];
element = 1;
Display(xs);

element = ref xs[^1];
element = 3;
Display(xs);
// Output:
// 0 0 0
// 1 0 0
// 1 0 3

Dans l’exemple précédent, la variable de référence element est initialisée en tant qu’alias au premier élément de tableau. Ensuite, elle est réassignée par référence (ref) pour faire référence au dernier élément de tableau.

Vous pouvez définir une variable locale ref readonly. Vous ne pouvez pas assigner une valeur à une variable ref readonly. Toutefois, vous pouvez réaffecter par référence (ref) une telle variable de référence, comme le montre l’exemple suivant :

int[] xs = [1, 2, 3];

ref readonly int element = ref xs[0];
// element = 100;  error CS0131: The left-hand side of an assignment must be a variable, property or indexer
Console.WriteLine(element);  // output: 1

element = ref xs[^1];
Console.WriteLine(element);  // output: 3

Vous pouvez affecter un retour de référence à une variable de référence, comme le montre l’exemple suivant :

using System;

public class NumberStore
{
    private readonly int[] numbers = [1, 30, 7, 1557, 381, 63, 1027, 2550, 511, 1023];

    public ref int GetReferenceToMax()
    {
        ref int max = ref numbers[0];
        for (int i = 1; i < numbers.Length; i++)
        {
            if (numbers[i] > max)
            {
                max = ref numbers[i];
            }
        }
        return ref max;
    }

    public override string ToString() => string.Join(" ", numbers);
}

public static class ReferenceReturnExample
{
    public static void Run()
    {
        var store = new NumberStore();
        Console.WriteLine($"Original sequence: {store.ToString()}");
        
        ref int max = ref store.GetReferenceToMax();
        max = 0;
        Console.WriteLine($"Updated sequence:  {store.ToString()}");
        // Output:
        // Original sequence: 1 30 7 1557 381 63 1027 2550 511 1023
        // Updated sequence:  1 30 7 1557 381 63 1027 0 511 1023
    }
}

Dans l’exemple précédent, la méthode GetReferenceToMax est une méthode returns-by-ref. Elle ne retourne pas la valeur maximale elle-même, mais un retour de référence qui est un alias à l’élément de tableau qui contient la valeur maximale. La méthode Run affecte un retour de référence à la variable de référence max. Ensuite, en affectant une valeur à max, elle met à jour le stockage interne de l’instance store. Vous pouvez également définir une méthode ref readonly. Les appelants d’une méthode ref readonly ne peuvent pas affecter une valeur à son retour de référence.

La variable d’itération de l’instruction foreach peut être une variable de référence. Pour plus d’informations, consultez la section foreach de l’article Instructions d’itération.

Dans les scénarios critiques pour les performances, l’utilisation de variables et de retours de référence peut améliorer les performances en évitant les opérations de copie potentiellement coûteuses.

Le compilateur garantit qu’une variable de référence ne vit pas plus longtemps que son référent et reste valide pendant toute sa durée de vie. Pour plus d’informations, consultez la section Contextes de sécurité de référence de la Spécification du langage C#.

Pour plus d’informations sur les champs ref, consultez la section Champs ref de l’article Types de structure ref.

scoped ref

Le mot clé contextuel scoped limite la durée de vie d’une valeur. Le modificateurscoped limite la durée de vie de ref-safe-to-escape ou safe-to-escape, respectivement, à la méthode actuelle. En fait, l’ajout du modificateur scoped déclare que votre code n’allongera pas la durée de vie de la variable.

Vous pouvez appliquer scoped à un paramètre ou à une variable locale. Le modificateur scoped peut être appliqué aux paramètres et aux variables locales quand le type est un ref struct. Sinon, le modificateur scoped peut être appliqué uniquement aux variables de référence locales. Cela inclut les variables locales déclarées avec le modificateur ref et les paramètres déclarés avec les modificateurs ou in, ref ou out.

Le modificateur scoped est implicitement ajouté à this dans les méthodes déclarées dans un struct, des paramètres out et des paramètres ref quand le type est un ref struct.

spécification du langage C#

Pour plus d’informations, consultez les sections suivantes de la spécification du langage C# :

Pour plus d’informations sur le modificateur scoped, consultez la note de proposition Améliorations des structures de bas niveau.

Voir aussi