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 queref struct
. - Un
ref struct
ne peut pas être converti (boxed) en System.ValueType ou System.Object. - Une variable
ref struct
ne peut pas être capturée dans une expression lambda ou une fonction locale. - Avant C# 13,
ref struct
les variables ne peuvent pas être utilisées dans uneasync
méthode. À compter de C# 13, vous ne pouvez par utiliser de variableref struct
dans le même bloc que l’expressionawait
dans une méthodeasync
. Toutefois, vous pouvez utiliser des variablesref struct
dans des méthodes synchrones, par exemple, dans les méthodes qui retournent Task ou Task<TResult>. - Avant C# 13, vous ne pouviez par utiliser de variables
ref struct
dans des itérateurs. À partir de C# 13, vous pouvez utiliser les typesref struct
et les variables localesref
dans des itérateurs, à condition qu’ils ne se trouvent pas dans des segments de code avec l’instructionyield return
. - Avant C# 13, un
ref struct
ne pouvait pas implémenter d’interfaces. À compter de C# 13, un structref
peut implémenter des interfaces, mais il doit adhérer aux règles de sécurité de référence. Par exemple, un typeref struct
ne peut pas être converti en type d’interface, car l’opération nécessite une conversion boxing. - Avant C# 13, un
ref struct
ne pouvait pas être un argument de type. À compter de C# 13, unref struct
peut être un argument de type quand le paramètre de type spécifie leallows ref struct
dans sa clausewhere
.
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 accesseurinit
. 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.
Modèle supprimable
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.
À compter de C# 13, vous pouvez également implémenter le IDisposable sur des types ref struct
. Toutefois, la résolution de surcharge préfère le modèle supprimable à la méthode de l’interface. Le compilateur se résout en méthode IDisposable.Dispose
uniquement lorsqu’une méthode appropriée Dispose
n’est pas trouvée.
Restrictions pour les types ref struct
implémentant une interface
Ces restrictions veillent à ce qu’un type ref struct
implémentant une interface obéisse aux règles de sécurité de référence.
- Un
ref struct
ne peut pas être converti en instance d’une interface qu’il implémente. Cette restriction inclut la conversion implicite lorsque vous utilisez un typeref struct
comme argument lorsque le paramètre est un type d’interface. La conversion entraîne une conversion boxing qui viole la sécurité de référence. - Un
ref struct
qui implémente une interface doit implémenter tous les membres de l’interface. Leref struct
doit implémenter des membres dans lesquels l’interface inclut une implémentation par défaut.
Le compilateur applique ces restrictions. Si vous écrivez des types ref struct
implémentant des interfaces, il est possible que chaque nouvelle mise à jour inclue de nouveaux membres d’interface par défaut. Votre application ne compilera que lorsque vous aurez fourni une implémentation pour ces nouvelles méthodes.
Important
Un ref struct
implémentant une interface inclut le risque de changements cassants binaires et de changements cassants de source ultérieurs. L’arrêt se produit si un ref struct
implémente une interface définie dans un autre assembly et que celui-ci fournit une mise à jour qui ajoute des membres par défaut à cette interface.
L’arrêt source se produit quand vous recompilez le ref struct
: il doit implémenter le nouveau membre même s’il existe une implémentation par défaut.
L’arrêt binaire se produit si vous mettez à niveau l’assembly externe sans recompiler le ref struct
type et si le code mis à jour appelle l’implémentation par défaut de la nouvelle méthode. Le runtime lève une exception quand le membre par défaut est accessible.
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.