ref (référence C#)ref (C# Reference)

Le mot clé ref indique une valeur qui est passée par référence.The ref keyword indicates a value that is passed by reference. Il est utilisé dans quatre contextes différents :It is used in four different contexts:

  • Dans une signature de méthode et dans un appel de méthode, pour passer un argument à une méthode par référence.In a method signature and in a method call, to pass an argument to a method by reference. Pour plus d’informations, consultez Passage d’un argument par référence.For more information, see Passing an argument by reference.
  • Dans une signature de méthode, pour retourner une valeur à l’appelant par référence.In a method signature, to return a value to the caller by reference. Pour plus d’informations, consultez Valeurs de retour de référence.For more information, see Reference return values.
  • Dans le corps d’un membre, pour indiquer qu’une valeur de retour de référence est stockée localement sous la forme d’une référence que l’appelant a l’intention de modifier, ou une variable locale accède généralement à une valeur par référence.In a member body, to indicate that a reference return value is stored locally as a reference that the caller intends to modify or, in general, a local variable accesses another value by reference. Pour plus d’informations, consultez Variables locales ref.For more information, see Ref locals.
  • Dans une déclaration de struct pour déclarer un ref struct ou un readonly ref struct.In a struct declaration to declare a ref struct or a readonly ref struct. Pour plus d’informations, consultez Types de structures ref.For more information, see ref struct types.

Passage d’un argument par référencePassing an argument by reference

Quand il est utilisé dans la liste de paramètres d’une méthode, le mot clé ref indique qu’un argument est passé par référence, et non par valeur.When used in a method's parameter list, the ref keyword indicates that an argument is passed by reference, not by value. Le mot clé ref fait du paramètre formel un alias de l’argument, qui doit être une variable.The ref keyword makes the formal parameter an alias for the argument, which must be a variable. En d’autres termes, toute opération portant sur le paramètre est effectuée sur l’argument.In other words, any operation on the parameter is made on the argument. Par exemple, si l’appelant passe une expression de variable locale ou une expression d’accès à un élément de tableau et que la méthode appelée remplace l’objet auquel fait référence le paramètre ref, la variable locale de l’appelant ou l’élément de tableau fait désormais référence au nouvel objet quand la méthode retourne une valeur.For example, if the caller passes a local variable expression or an array element access expression, and the called method replaces the object to which the ref parameter refers, then the caller’s local variable or the array element now refers to the new object when the method returns.

Notes

Ne confondez pas le concept de passage par référence avec celui de types de référence.Do not confuse the concept of passing by reference with the concept of reference types. Les deux concepts ne sont pas identiques.The two concepts are not the same. Un paramètre de méthode peut être modifié par ref, qu'il s'agisse d'un type valeur ou d'un type référence.A method parameter can be modified by ref regardless of whether it is a value type or a reference type. Il n'y a aucun boxing d'un type valeur lorsqu'il est passé par référence.There is no boxing of a value type when it is passed by reference.

Pour utiliser un paramètre ref, la définition de la méthode et la méthode d'appel doivent utiliser explicitement le mot clé ref, comme indiqué dans l'exemple suivant.To use a ref parameter, both the method definition and the calling method must explicitly use the ref keyword, as shown in the following example.

void Method(ref int refArgument)
{
    refArgument = refArgument + 44;
}

int number = 1;
Method(ref number);
Console.WriteLine(number);
// Output: 45

Un argument passé à un paramètre ref ou in doit être initialisé avant d’être transmis.An argument that is passed to a ref or in parameter must be initialized before it is passed. Cette obligation diffère des paramètres out, dont les arguments ne doivent pas être explicitement initialisés avant d’être passés.This differs from out parameters, whose arguments do not have to be explicitly initialized before they are passed.

Les membres d’une classe ne peuvent pas avoir de signatures qui diffèrent uniquement par ref, in ou out.Members of a class can't have signatures that differ only by ref, in, or out. Une erreur de compilation se produit si la seule différence entre deux membres d’un type est que l’un d’eux a un paramètre ref et que l’autre un a un paramètre out ou in.A compiler error occurs if the only difference between two members of a type is that one of them has a ref parameter and the other has an out, or in parameter. Le code suivant, par exemple, ne se compile pas.The following code, for example, doesn't compile.

class CS0663_Example
{
    // Compiler error CS0663: "Cannot define overloaded 
    // methods that differ only on ref and out".
    public void SampleMethod(out int i) { }
    public void SampleMethod(ref int i) { }
}

Toutefois, les méthodes peuvent être surchargées quand une méthode a un paramètre ref, in ou out et que l’autre a un paramètre de valeur, comme illustré dans l’exemple suivant.However, methods can be overloaded when one method has a ref, in, or out parameter and the other has a value parameter, as shown in the following example.

class RefOverloadExample
{
    public void SampleMethod(int i) { }
    public void SampleMethod(ref int i) { }
}

Dans d'autres situations nécessitant une correspondance de signature, comme le masquage ou la substitution, in, ref et out font partie de la signature et ne correspondent pas l’un à l’autre.In other situations that require signature matching, such as hiding or overriding, in, ref, and out are part of the signature and don't match each other.

Les propriétés ne sont pas des variables.Properties are not variables. Ce sont des méthodes et ne peuvent pas être passées aux paramètres ref.They are methods, and cannot be passed to ref parameters.

Vous ne pouvez pas utiliser les mots clés ref, in ou out pour les types de méthodes suivants :You can't use the ref, in, and out keywords for the following kinds of methods:

  • Méthodes async, que vous définissez à l’aide du modificateur async.Async methods, which you define by using the async modifier.
  • Les méthodes Iterator, qui incluent une instruction yield return ou yield break.Iterator methods, which include a yield return or yield break statement.

Passage d’un argument par référence : ExemplePassing an argument by reference: An example

Les exemples précédents passent les types valeur par référence.The previous examples pass value types by reference. Vous pouvez également utiliser le mot clé ref pour passer les types référence par référence.You can also use the ref keyword to pass reference types by reference. Le passage d’un type référence par référence permet à la méthode appelée de remplacer l’objet auquel fait référence le paramètre de référence dans l’appelant.Passing a reference type by reference enables the called method to replace the object to which the reference parameter refers in the caller. L'emplacement de stockage de l'objet est passé à la méthode comme valeur du paramètre de référence.The storage location of the object is passed to the method as the value of the reference parameter. Si vous modifiez la valeur de l'emplacement de stockage du paramètre (pour pointer vers un nouvel objet), vous modifiez également l'emplacement de stockage auquel fait référence l'appelant.If you change the value in the storage location of the parameter (to point to a new object), you also change the storage location to which the caller refers. L'exemple suivant passe une instance d'un type référence en tant que paramètre ref.The following example passes an instance of a reference type as a ref parameter.

class Product
{
    public Product(string name, int newID)
    {
        ItemName = name;
        ItemID = newID;
    }

    public string ItemName { get; set; }
    public int ItemID { get; set; }
}

private static void ChangeByReference(ref Product itemRef)
{
    // Change the address that is stored in the itemRef parameter.   
    itemRef = new Product("Stapler", 99999);

    // You can change the value of one of the properties of
    // itemRef. The change happens to item in Main as well.
    itemRef.ItemID = 12345;
}

private static void ModifyProductsByReference()
{
    // Declare an instance of Product and display its initial values.
    Product item = new Product("Fasteners", 54321);
    System.Console.WriteLine("Original values in Main.  Name: {0}, ID: {1}\n",
        item.ItemName, item.ItemID);

    // Pass the product instance to ChangeByReference.
    ChangeByReference(ref item);
    System.Console.WriteLine("Back in Main.  Name: {0}, ID: {1}\n",
        item.ItemName, item.ItemID);
}

// This method displays the following output:
// Original values in Main.  Name: Fasteners, ID: 54321
// Back in Main.  Name: Stapler, ID: 12345        

Pour plus d’informations sur la manière de passer des types référence par valeur et par référence, consultez Passage de paramètres de type référence .For more information about how to pass reference types by value and by reference, see Passing Reference-Type Parameters.

Valeurs de retour de référenceReference return values

Les valeurs de retour de référence (ou retours ref) sont des valeurs qu’une méthode retourne par référence à l’appelant.Reference return values (or ref returns) are values that a method returns by reference to the caller. Autrement dit, l’appelant peut modifier la valeur retournée par une méthode, et ce changement est reflété dans l’état de l’objet qui contient la méthode.That is, the caller can modify the value returned by a method, and that change is reflected in the state of the object that contains the method.

Une valeur de retour de référence est définie à l’aide du mot clé ref :A reference return value is defined by using the ref keyword:

  • Dans la signature de la méthode.In the method signature. Par exemple, la signature de méthode suivante indique que la méthode GetCurrentPrice retourne une valeur Decimal par référence.For example, the following method signature indicates that the GetCurrentPrice method returns a Decimal value by reference.
public ref decimal GetCurrentPrice()
  • Entre le jeton return et la variable retournée dans une instruction return dans la méthode.Between the return token and the variable returned in a return statement in the method. Par exemple :For example:
return ref DecimalArray[0];

Pour que l’appelant puisse modifier l’état de l’objet, la valeur de retour de référence doit être stockée dans une variable qui est explicitement définie comme variable locale ref.In order for the caller to modify the object's state, the reference return value must be stored to a variable that is explicitly defined as a ref local.

La méthode appelée peut également déclarer la valeur renvoyée en tant que ref readonly pour renvoyer la valeur par référence et faire en sorte que le code d'appel ne puisse pas modifier la valeur renvoyée.The called method may also declare the return value as ref readonly to return the value by reference, and enforce that the calling code cannot modify the returned value. La méthode d’appel peut éviter de copier la valeur renvoyée en stockant la valeur dans une variable ref readonly locale.The calling method can avoid copying the returned valued by storing the value in a local ref readonly variable.

Pour obtenir un exemple, voir Exemple de valeurs de retour de référence et de variables locales ref.For an example, see A ref returns and ref locals example.

Variables locales refRef locals

Une variable locale ref est utilisée pour faire référence aux valeurs retournées à l’aide de return ref.A ref local variable is used to refer to values returned using return ref. Vous ne pouvez pas initialiser une variable locale ref en valeur de retour non ref.A ref local variable cannot be initialized to a non-ref return value. En d’autres termes, la partie droite de l’initialisation doit être une référence.In other words, the right hand side of the initialization must be a reference. Toute modification apportée à la valeur de la variable locale ref est reflétée dans l’état de l’objet dont la méthode a retourné la valeur par référence.Any modifications to the value of the ref local are reflected in the state of the object whose method returned the value by reference.

Vous définissez une variable locale ref à l’aide du mot clé ref avant la déclaration de la variable, ainsi qu’immédiatement avant l’appel à la méthode qui retourne la valeur par référence.You define a ref local by using the ref keyword before the variable declaration, as well as immediately before the call to the method that returns the value by reference.

Par exemple, l’instruction suivante définit une valeur de variable locale ref qui est retournée par une méthode nommée GetEstimatedValue :For example, the following statement defines a ref local value that is returned by a method named GetEstimatedValue:

ref decimal estValue = ref Building.GetEstimatedValue();

Vous pouvez accéder à une valeur par référence de la même façon.You can access a value by reference in the same way. Dans certains cas, l’accès à une valeur par référence augmente les performances en évitant une opération de copie potentiellement coûteuse.In some cases, accessing a value by reference increases performance by avoiding a potentially expensive copy operation. Par exemple, l’instruction suivante montre comment il est possible de définir une valeur locale ref qui est utilisée pour référencer une valeur.For example, the following statement shows how one can define a ref local value that is used to reference a value.

ref VeryLargeStruct reflocal = ref veryLargeStruct;

Notez que dans les deux exemples, le mot clé ref doit être utilisé aux deux emplacements, sans quoi le compilateur génère l’erreur CS8172, « Impossible d’initialiser une variable par référence avec une valeur ».Note that in both examples the ref keyword must be used in both places, or the compiler generates error CS8172, "Cannot initialize a by-reference variable with a value."

À partir de C# 7.3, la variable d’itération de l’instruction foreach peut être une variable locale ref ou une variable locale ref readonly.Beginning with C# 7.3, the iteration variable of the foreach statement can be ref local or ref readonly local variable. Pour plus d’informations, voir l’article Instruction foreach.For more information, see the foreach statement article.

Variable locale ref readonlyRef readonly locals

Une variable locale ref readonly est utilisée pour se référer à des valeurs renvoyées par la méthode ou par la propriété comprenant ref readonly dans sa signature et utilise return ref.A ref readonly local is used to refer to values returned by the method or property that has ref readonly in its signature and uses return ref. Une variable ref readonly combine les propriétés d’une variable locale ref avec une variable readonly : c’est un alias du stockage auquel elle est assignée et qui ne peut pas être modifié.A ref readonly variable combines the properties of a ref local variable with a readonly variable: it is an alias to the storage it's assigned to, and it cannot be modified.

Exemple de retours ref et de variables locales refA ref returns and ref locals example

L’exemple suivant définit une classe Book qui a deux champs String, Title et Author.The following example defines a Book class that has two String fields, Title and Author. Il définit également une classe BookCollection qui inclut un tableau privé d’objets Book.It also defines a BookCollection class that includes a private array of Book objects. Des objets livres individuels sont retournés par référence en appelant sa méthode GetBookByTitle.Individual book objects are returned by reference by calling its GetBookByTitle method.


public class Book
{
    public string Author;
    public string Title;
}

public class BookCollection
{
    private Book[] books = { new Book { Title = "Call of the Wild, The", Author = "Jack London" },
                        new Book { Title = "Tale of Two Cities, A", Author = "Charles Dickens" }
                       };
    private Book nobook = null;

    public ref Book GetBookByTitle(string title)
    {
        for (int ctr = 0; ctr < books.Length; ctr++)
        {
            if (title == books[ctr].Title)
                return ref books[ctr];
        }
        return ref nobook;
    }

    public void ListBooks()
    {
        foreach (var book in books)
        {
            Console.WriteLine($"{book.Title}, by {book.Author}");
        }
        Console.WriteLine();
    }
}

Quand l’appelant stocke la valeur retournée par la méthode GetBookByTitle comme variable locale ref, les modifications apportées par l’appelant à la valeur de retour sont reflétées dans l’objet BookCollection, comme le montre l’exemple suivant.When the caller stores the value returned by the GetBookByTitle method as a ref local, changes that the caller makes to the return value are reflected in the BookCollection object, as the following example shows.

var bc = new BookCollection();
bc.ListBooks();

ref var book = ref bc.GetBookByTitle("Call of the Wild, The");
if (book != null)
    book = new Book { Title = "Republic, The", Author = "Plato" };
bc.ListBooks();
// The example displays the following output:
//       Call of the Wild, The, by Jack London
//       Tale of Two Cities, A, by Charles Dickens
//       
//       Republic, The, by Plato
//       Tale of Two Cities, A, by Charles Dickens

Types de structures refRef struct types

L’ajout du modificateur ref à une déclaration struct définit que les instances de ce type doivent être allouées par la pile.Adding the ref modifier to a struct declaration defines that instances of that type must be stack allocated. En d’autres termes, les instances de ces types ne peuvent jamais être créées sur un segment de mémoire en tant que membre d’une autre classe.In other words, instances of these types can never be created on the heap as a member of another class. Cette fonctionnalité vise principalement Span<T> et ses structures associées.The primary motivation for this feature was Span<T> and related structures.

La conservation d’un type ref struct comme variable allouée par la pile introduit plusieurs règles que le compilateur applique pour tous les types ref struct.The goal of keeping a ref struct type as a stack-allocated variable introduces several rules that the compiler enforces for all ref struct types.

  • Vous ne pouvez pas effectuer d’opération box sur un ref struct.You can't box a ref struct. Vous ne pouvez pas assigner un type ref struct à une variable de type object, dynamic ou tout type interface.You cannot assign a ref struct type to a variable of type object, dynamic, or any interface type.
  • Les types ref struct ne peuvent pas implémenter les interfaces.ref struct types cannot implement interfaces.
  • Vous ne pouvez pas déclarer ref struct comme membre de champ d’une classe ou d’un struct normal.You can't declare a ref struct as a field member of a class or a normal struct. Cela comprend la déclaration d’une propriété implémentée automatiquement, qui crée un champ de stockage généré par le compilateur.This includes declaring an auto-implemented property, which creates a compiler generated backing field.
  • Vous ne pouvez pas déclarer des variables locales qui sont des types ref struct dans des méthodes async.You cannot declare local variables that are ref struct types in async methods. Vous pouvez les déclarer dans des méthodes synchrones qui retournent des types semblables à Task, Task<TResult> ou Task.You can declare them in synchronous methods that return Task, Task<TResult> or Task-like types.
  • Vous ne pouvez pas déclarer de variables locales ref struct dans des itérateurs.You cannot declare ref struct local variables in iterators.
  • Vous ne pouvez pas capturer de variables ref struct dans des expressions lambda ou des fonctions locales.You cannot capture ref struct variables in lambda expressions or local functions.

Ces restrictions garantissent que vous n’utilisiez pas accidentellement une ref struct d’une manière qui pourrait la promouvoir auprès du tas managé.These restrictions ensure you don't accidentally use a ref struct in a manner that could promote it to the managed heap.

Vous pouvez combiner des modificateurs pour déclarer une structure en tant que readonly ref.You can combine modifiers to declare a struct as readonly ref. Une readonly ref struct combine les avantages et les restrictions des déclarations ref struct et readonly struct.A readonly ref struct combines the benefits and restrictions of ref struct and readonly struct declarations.

spécification du langage C#C# language specification

Pour plus d'informations, voir la spécification du langage C#.For more information, see the C# Language Specification. La spécification du langage est la source de référence pour la syntaxe C# et son utilisation.The language specification is the definitive source for C# syntax and usage.

Voir aussiSee also