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.
Remarque
Cet article est une spécification de fonctionnalité. La spécification sert de document de conception pour la fonctionnalité. Elle inclut les changements de spécification proposés, ainsi que les informations nécessaires à la conception et au développement de la fonctionnalité. Ces articles sont publiés jusqu'à ce que les changements proposés soient finalisés et incorporés dans la spécification ECMA actuelle.
Il peut y avoir des différences entre la spécification de la fonctionnalité et l'implémentation réalisée. Ces différences sont consignées dans les notes pertinentes de la réunion de conception linguistique (LDM).
Pour en savoir plus sur le processus d'adoption des speclets de fonctionnalité dans la norme du langage C#, consultez l'article sur les spécifications.
Problème de champion : https://github.com/dotnet/csharplang/issues/6065
Récapitulatif
Il s’agit d’une révision sur la fonctionnalité initiale d’entiers natifs (spec), où les types nint/nuint étaient distincts des types sous-jacents System.IntPtr/System.UIntPtr.
En résumé, nous traitons maintenant nint/nuint en tant qu’alias de types simples System.IntPtr/System.UIntPtr, comme nous le faisons pour int par rapport à System.Int32. L’indicateur de fonctionnalité runtime System.Runtime.CompilerServices.RuntimeFeature.NumericIntPtr déclenche ce nouveau comportement.
Création
8.3.5 Types simples
C# fournit un ensemble de types struct prédéfinis appelés types simples. Les types simples sont identifiés par le biais de mots clés, mais ces mots clés sont simplement des alias pour les types struct prédéfinis dans l’espace de noms System, comme décrit dans le tableau ci-dessous.
| Mot-clé | Type aliasé |
|---|---|
sbyte |
System.SByte |
byte |
System.Byte |
short |
System.Int16 |
ushort |
System.UInt16 |
int |
System.Int32 |
uint |
System.UInt32 |
nint |
System.IntPtr |
nuint |
System.UIntPtr |
long |
System.Int64 |
ulong |
System.UInt64 |
char |
System.Char |
float |
System.Single |
double |
System.Double |
bool |
System.Boolean |
decimal |
System.Decimal |
[...]
8.3.6 Types intégraux
C# prend en charge onze types entiers : sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, et char. [...]
8.8 Types non managés
En d’autres termes, un unmanaged_type est l’un des types suivants :
-
sbyte,byte,short,ushort,int,uint,nint,nuint,long,ulong,char,float,double,decimaloubool. - Tout enum_type.
- Tout struct_type défini par l’utilisateur qui n’est pas un type construit et ne contient que des champs de unmanaged_type.
- Dans un code non sécurisé, tout pointer_type.
10.2.3 Conversions numériques implicites
Les conversions numériques implicites sont les suivantes :
- De
sbyteversshort,int,nint,long,float,doubleoudecimal. - De
byteversshort,ushort,int,uint,nint,nuint,long,ulong,float,doubleoudecimal. - De
shortversint,nint,long,float,doubleoudecimal. - De
ushortversint,uint,nint,nuint,long,ulong,float,doubleoudecimal. - De
intversnint,long,float,doubleoudecimal. - De
uintversnuint,long,ulong,float,doubleoudecimal. -
De
nintverslong,float,doubleoudecimal. -
De
nuintversulong,float,doubleoudecimal. - De
longversfloat,doubleoudecimal. - De
ulongversfloat,doubleoudecimal. - De
charversushort,int,uint,nint,nuint,long,ulong,float,doubleoudecimal. - De
floatversdouble.
[...]
10.2.11 Conversions d’expressions constantes implicites
Une conversion d’expression constante implicite permet les conversions suivantes :
- Une constant_expression de type
intpeut être convertie en typesbyte,byte,short,ushort,uint,nint,nuintouulong, à condition que la valeur de constant_expression se trouve dans la plage du type de destination. [...]
10.3.2 Conversions numériques explicites
Les conversions numériques explicites sont les conversions d’un numeric_type vers un autre numeric_type pour lesquelles une conversion numérique implicite n’existe pas déjà :
- De
sbyteversbyte,ushort,uint,nuint,ulongouchar. - De
byteverssbyteouchar. - De
shortverssbyte,byte,ushort,uint,nuint,ulongouchar. - De
ushortverssbyte,byte,shortouchar. - De
intverssbyte,byte,short,ushort,uint,nuint,ulongouchar. - De
uintverssbyte,byte,short,ushort,int,nintouchar. - De
longverssbyte,byte,short,ushort,int,uint,nint,nuint,ulongouchar. -
De
nintverssbyte,byte,short,ushort,int,uint,nuint,ulongouchar. -
De
nuintverssbyte,byte,short,ushort,int,uint,nint,longouchar. - De
ulongverssbyte,byte,short,ushort,int,uint,nint,nuint,longouchar. - De
charverssbyte,byteoushort. - De
floatverssbyte,byte,short,ushort,int,uint,nint,nuint,long,ulong,charoudecimal. - De
doubleverssbyte,byte,short,ushort,int,uint,nint,nuint,long,ulong,char,floatoudecimal. - De
decimalverssbyte,byte,short,ushort,int,uint,nint,nuint,long,ulong,char,floatoudouble.
[...]
10.3.3 Conversions d’énumérations explicites
Les conversions d’énumérations explicites sont les suivantes :
- De
sbyte,byte,short,ushort,int,uint,nint,nuint,long,ulong,char,float,doubleoudecimalvers n’importe quel enum_type. - De n’importe quel enum_type vers
sbyte,byte,short,ushort,int,uint,nint,nuint,long,ulong,char,float,doubleoudecimal. - De tout enum_type à tout autre enum_type.
12.6.4.7 Meilleure cible de conversion
Étant donné deux types T₁ et T₂, T₁ est une meilleure cible de conversion que T₂ si l'un des critères suivants est rempli :
- Une conversion implicite de
T₁versT₂existe et aucune conversion implicite deT₂versT₁n’existe -
T₁estTask<S₁>,T₂estTask<S₂>etS₁est une meilleure cible de conversion queS₂ -
T₁estS₁ouS₁?oùS₁est un type intégral signé etT₂estS₂ouS₂?oùS₂est un type intégral non signé. En particulier : [...]
12.8.12 Accès aux éléments
[...] Le nombre d’expressions dans la argument_list doit être identique au rang du array_type, et chaque expression doit être de type int, uint, nint, nuint, , long ou ulong,, ou doit être implicitement convertible dans l’un ou plusieurs de ces types.
11.8.12.2 Accès aux tableaux
[...] Le nombre d’expressions dans la argument_list doit être identique au rang du array_type, et chaque expression doit être de type int, uint, nint, nuint, , long ou ulong,, ou doit être implicitement convertible dans l’un ou plusieurs de ces types.
[...] Le traitement à l’exécution d’un accès à un tableau de la forme P[A], où P est une primary_no_array_creation_expression d’un array_type et A est une argument_list, consiste en les étapes suivantes : [...]
- Les expressions d’index de la argument_list sont évaluées dans l’ordre, de gauche à droite. Après l'évaluation de chaque expression d'index, une conversion implicite vers l'un des types suivants est effectuée :
int,uint,nint,nuint,long,ulong. Le premier type dans cette liste pour lequel une conversion implicite existe est choisi. [...]
12.8.16 Opérateurs suffixés d’incrémentation et de décrémentation
La résolution de surcharge des opérateurs unaires est appliquée pour sélectionner une implémentation spécifique de l’opérateur. Les opérateurs prédéfinis ++ et -- existent pour les types suivants : sbyte, byte, short, ushort, int, uint, nint, nuint,long, ulong, char, float, double, decimal et tout type enum.
12.9.2 Opérateur unaire plus
Les opérateurs unaire plus prédéfinis sont :
...
nint operator +(nint x);
nuint operator +(nuint x);
12.9.3 Opérateur unaire moins
Les opérateurs unaire moins prédéfinis sont :
Négation entière :
... nint operator –(nint x);
12.8.16 Opérateurs suffixés d’incrémentation et de décrémentation
Les opérateurs prédéfinis ++ et -- existent pour les types suivants : sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal et tout type enum.
11.7.19 Expressions de valeur par défaut
En outre, une default_value_expression est une expression constante si le type est l’un des types de valeur suivants : sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal, bool, ou tout type d’enum.
12.9.5 Opérateur complément binaire
Les opérateurs de complément bit à bit prédéfinis sont :
...
nint operator ~(nint x);
nuint operator ~(nuint x);
12.9.6 Opérateurs préfixés d’incrémentation et de décrémentation
Les opérateurs prédéfinis ++ et -- existent pour les types suivants : sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal et tout type enum.
12.10 opérateurs arithmétiques
12.10.2 opérateur de multiplication
Les opérateurs de multiplication prédéfinis sont listés ci-dessous. Tous les opérateurs calculent le produit de x et y.
Multiplication des entiers :
... nint operator *(nint x, nint y); nuint operator *(nuint x, nuint y);
12.10.3 opérateur de division
Les opérateurs de division prédéfinis sont listés ci-dessous. Tous les opérateurs calculent le quotient de x et y.
Division entière :
... nint operator /(nint x, nint y); nuint operator /(nuint x, nuint y);
12.10.4 Opérateur de reste
Les opérateurs de reste prédéfinis sont listés ci-dessous. Les opérateurs calculent tous le reste de la division entre x et y.
Reste entier :
... nint operator %(nint x, nint y); nuint operator %(nuint x, nuint y);
12.10.5 opérateur d’addition
Addition entière :
... nint operator +(nint x, nint y); nuint operator +(nuint x, nuint y);
12.10.6 Opérateur de soustraction
Soustraction entière :
... nint operator –(nint x, nint y); nuint operator –(nuint x, nuint y);
12.11 Opérateurs de décalage
Les opérateurs de décalage prédéfinis sont listés ci-dessous.
Décalage vers la gauche :
... nint operator <<(nint x, int count); nuint operator <<(nuint x, int count);Décalage vers la droite :
... nint operator >>(nint x, int count); nuint operator >>(nuint x, int count);L’opérateur
>>déplacexvers la droite d'un nombre de bits calculé comme décrit ci-dessous.Lorsque
xest de typeint,nintoulong, les bits de poids faible dexsont supprimés, les bits restants sont décalés vers la droite et les positions de bits vides de poids fort sont mises à zéro sixest non négatif, et mises à un sixest négatif.Lorsque
xest de typeuint,nuintouulong, les bits de poids faible dexsont supprimés, les bits restants sont décalés vers la droite et les positions de bits vides de poids fort sont mises à zéro.Décalage logique à droite :
... nint operator >>>(nint x, int count); nuint operator >>>(nuint x, int count);
Pour les opérateurs prédéfinis, le nombre de bits à décaler est calculé comme suit : [...]
- Lorsque le type de
xestnintounuint, le décalage est déterminé par les cinq bits de poids faible decountsur une plateforme 32 bits, ou les six bits de poids faible decountsur une plateforme 64 bits.
12.12 opérateurs relationnels et de test de type
12.12.2 opérateurs de comparaison entiers
Les opérateurs de comparaison entiers prédéfinis sont :
...
bool operator ==(nint x, nint y);
bool operator ==(nuint x, nuint y);
bool operator !=(nint x, nint y);
bool operator !=(nuint x, nuint y);
bool operator <(nint x, nint y);
bool operator <(nuint x, nuint y);
bool operator >(nint x, nint y);
bool operator >(nuint x, nuint y);
bool operator <=(nint x, nint y);
bool operator <=(nuint x, nuint y);
bool operator >=(nint x, nint y);
bool operator >=(nuint x, nuint y);
12.12 Opérateurs logiques
12.12.2 Opérateurs logiques entiers
Les opérateurs logiques entiers prédéfinis sont :
...
nint operator &(nint x, nint y);
nuint operator &(nuint x, nuint y);
nint operator |(nint x, nint y);
nuint operator |(nuint x, nuint y);
nint operator ^(nint x, nint y);
nuint operator ^(nuint x, nuint y);
12.22 Expressions constantes
Une expression constante peut être un type de valeur ou un type de référence. Si une expression constante est un type de valeur, il doit s’agir de l’un des types suivants : sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal, bool, ou tout type d’enum.
[...]
Une conversion implicite d’expression constante permet de convertir une expression constante de type int en sbyte, byte, short, ushort, uint, nint, nuint, ou ulong, à condition que la valeur de l’expression constante se trouve dans la plage du type de destination.
17.4 Accès aux éléments de tableau
Les éléments de tableau sont accessibles à l’aide d’expressions element_access de la forme A[I₁, I₂, ..., Iₓ], où A est une expression de type de tableau et chaque Iₑ est une expression de type int, uint, nint, nuint,long, ulong ou peut être implicitement convertie en un ou plusieurs de ces types. Le résultat de l’accès à un élément de tableau est une variable, à savoir l’élément de tableau sélectionné par les index.
23.5 Conversions de pointeur
23.5.1 Général
[...]
En outre, dans un contexte non sécurisé, l’ensemble de conversions explicites disponibles est étendu pour inclure les conversions de pointeurs explicites suivantes :
- De tout pointer_type à tout autre pointer_type.
- De
sbyte,byte,short,ushort,int,uint,nint,nuint,longouulongvers n’importe quel pointer_type. - De n’importe quel pointer_type vers
sbyte,byte,short,ushort,int,uint,nint,nuint,longouulong.
23.6.4 Accès aux éléments de pointeur
[...] Dans un accès à un élément de pointeur sous la forme P[E], P doit être une expression de type de pointeur autre que void*, et E doit être une expression pouvant être implicitement convertie en int, uint, nint, nuint, long ou ulong.
23.6.7 Arithmétique des pointeurs
Dans un contexte non sécurisé, l’opérateur + et l’opérateur – peuvent être appliqués aux valeurs de tous les types de pointeurs, à l‘exception de void*. Ainsi, pour chaque type de pointeur T*, les opérateurs suivants sont implicitement définis :
[...]
T* operator +(T* x, nint y);
T* operator +(T* x, nuint y);
T* operator +(nint x, T* y);
T* operator +(nuint x, T* y);
T* operator -(T* x, nint y);
T* operator -(T* x, nuint y);
Étant donné une expression P de type de pointeur T* et une expression N de type int, uint, nint, nuint, long ou ulong, les expressions P + N et N + P calculent la valeur du pointeur de type T* qui résulte de l’ajout de N * sizeof(T) à l’adresse donnée par P. De même, l’expression P – N calcule la valeur du pointeur de type T* qui résulte de la soustraction de N * sizeof(T) de l’adresse donnée par P.
Considérations diverses
Changements cassants
L'un des principaux impacts de cette conception est que System.IntPtr et System.UIntPtr gagnent des opérateurs intégrés (conversions, unaires et binaires).
Ceux-ci incluent les opérateurs checked, ce qui signifie que les opérateurs suivants sur ces types lanceront désormais une exception en cas de dépassement :
IntPtr + intIntPtr - intIntPtr -> intlong -> IntPtrvoid* -> IntPtr
Encodage des métadonnées
Cette conception signifie que nint et nuint peuvent simplement être émis en tant que System.IntPtr et System.UIntPtr, sans utiliser System.Runtime.CompilerServices.NativeIntegerAttribute.
De même, lors du chargement des métadonnées, NativeIntegerAttribute peut être ignoré.
C# feature specifications