Note
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier les répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de changer de répertoire.
Types de structure
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 structne peut pas être le type d’élément d’un tableau. - Un
ref structne peut pas être un type déclaré d’un champ d’une classe ou un type autre queref struct. - Un
ref structne peut pas être converti (boxed) en System.ValueType ou System.Object. - Une variable
ref structne peut pas être capturée dans une expression lambda ou une fonction locale. - Avant C# 13,
ref structles variables ne peuvent pas être utilisées dans uneasyncméthode. À compter de C# 13, vous ne pouvez par utiliser de variableref structdans le même bloc que l’expressionawaitdans une méthodeasync. Toutefois, vous pouvez utiliser des variablesref structdans 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 structdans des itérateurs. À partir de C# 13, vous pouvez utiliser les typesref structet les variables localesrefdans des itérateurs, à condition qu’ils ne se trouvent pas dans des segments de code avec l’instructionyield return. - Avant C# 13, un
ref structne pouvait pas implémenter d’interfaces. À compter de C# 13, un structrefpeut implémenter des interfaces, mais il doit adhérer aux règles de sécurité de référence. Par exemple, un typeref structne peut pas être converti en type d’interface, car l’opération nécessite une conversion boxing. - Avant C# 13, un
ref structne pouvait pas être un argument de type. À compter de C# 13, unref structpeut être un argument de type quand le paramètre de type spécifie leallows ref structdans 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, ref struct et System.Span<T> sont des exemples de System.ReadOnlySpan<T>.
Champs ref
Vous pouvez déclarer un ref champ dans un ref struct, comme l’illustre 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= refuniquement à 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 a une méthode d’instance Dispose accessible, sans paramètre et avec un void type de retour. 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 structne peut pas être converti en instance d’une interface qu’il implémente. Cette restriction inclut la conversion implicite lorsque vous utilisez un typeref structcomme 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. Uneref structpeut déclarer des méthodes comme déclarations d’interface explicites. Toutefois, ces méthodes sont accessibles uniquement à partir de méthodes génériques où le paramètre de typeallows ref structeffectue des opérations. - Un
ref structqui implémente une interface doit implémenter tous les membres de l’interface d’instance. Leref structdoit implémenter des membres d’instance même lorsque 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. Tant que vous n’avez pas fourni d’implémentation pour les nouvelles méthodes d’instance, votre application ne compile pas. Vous ne pouvez pas fournir une implémentation spécifique pour une méthode d’interface static avec une implémentation par défaut.
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 une ref struct interface implémente une interface définie dans un autre assembly et que cet assembly fournit une mise à jour qui ajoute des membres par défaut à cette interface.
L’arrêt source se produit lorsque vous recompilez l'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.