Types de structure ref (Informations de référence sur C#)

Vous pouvez utiliser le modificateur ref dans la déclaration d’un type de structure. Les instances d’un type ref struct sont allouées sur la pile et ne peuvent pas passer au tas managé. Pour le garantir, le compilateur limite l’utilisation des types ref struct comme suit :

  • Un ref struct ne peut pas être le type d’élément d’un tableau.
  • Un ref struct ne peut pas être un type déclaré d’un champ d’une classe ou un type autre que ref struct.
  • Un ref struct ne peut pas implémenter d’interfaces.
  • Un ref struct ne peut pas être converti (boxed) en System.ValueType ou System.Object.
  • Un ref struct ne peut pas être un argument de type.
  • Une variable ref struct ne peut pas être capturée par une expression lambda ou une fonction locale.
  • Une variable ref struct ne peut pas être utilisée dans une méthode async. Toutefois, vous pouvez utiliser des variables ref struct dans des méthodes synchrones, par exemple, dans les méthodes qui retournent Task ou Task<TResult>.
  • Une variable ref struct ne peut pas être utilisée dans des itérateurs.

Vous pouvez définir un ref struct supprimable. Pour ce faire, assurez-vous qu’un ref struct est conforme au modèle supprimable. Autrement dit, il doit avoir une méthode Dispose d’instance qui soit accessible et sans paramètre, avec un type de retour void. Vous pouvez utiliser l’instruction ou la déclaration using avec une instance d’un ref struct supprimable.

En règle générale, vous définissez un type ref struct lorsque vous avez besoin d’un type incluant aussi des membres de données des types ref struct :

public ref struct CustomRef
{
    public bool IsValid;
    public Span<int> Inputs;
    public Span<int> Outputs;
}

Pour déclarer un ref struct en readonly, combinez les modificateurs readonly et ref dans la déclaration de type (le modificateur readonly doit être placé avant le modificateurref) :

public readonly ref struct ConversionRequest
{
    public ConversionRequest(double rate, ReadOnlySpan<double> values)
    {
        Rate = rate;
        Values = values;
    }

    public double Rate { get; }
    public ReadOnlySpan<double> Values { get; }
}

Dans .NET, System.Span<T> et System.ReadOnlySpan<T> sont des exemples de ref struct.

Champs ref

À compter de C# 11, vous pouvez déclarer un champ ref dans un ref struct, comme le montre l’exemple suivant :

public ref struct RefFieldExample
{
    private ref int number;

    public int GetNumber()
    {
        if (System.Runtime.CompilerServices.Unsafe.IsNullRef(ref number))
        {
            throw new InvalidOperationException("The number ref field is not initialized.");
        }

        return number;
    }
}

Un champ ref peut avoir la valeur null. Utilisez la méthode Unsafe.IsNullRef<T>(T) pour déterminer si un champ ref a la valeur null.

Vous pouvez appliquer le modificateur readonly à un champ ref des manières suivantes :

  • readonly ref : vous pouvez réaffecter le ref d’un tel champ avec l’opérateur = ref uniquement à l’intérieur d’un constructeur ou d’un accesseurinit. Vous pouvez affecter une valeur avec l’opérateur = à n’importe quel moment autorisé par le modificateur d’accès du champ.
  • ref readonly : vous ne pouvez à aucun moment affecter une valeur avec l’opérateur = à un tel champ. En revanche, vous pouvez réaffecter le ref d’un champ avec l’opérateur = ref.
  • readonly ref readonly : vous pouvez uniquement réaffecter le ref d’un tel champ dans un constructeur ou dans un accesseur init. Vous ne pouvez à aucun moment affecter une valeur au champ.

Le compilateur garantit qu’une référence stockée dans un champ ref ne survit pas à son référent.

La fonctionnalité de champs ref permet une implémentation sécurisée de types tels que System.Span<T> :

public readonly ref struct Span<T>
{
    internal readonly ref T _reference;
    private readonly int _length;

    // Omitted for brevity...
}

Le type Span<T> stocke une référence par le biais de laquelle il accède aux éléments contigus en mémoire. Le recours à une référence permet à une instance Span<T> d’éviter de copier le stockage auquel elle fait référence.

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 les champs ref, consultez la note de proposition Améliorations des structs de bas niveau.

Voir aussi