IntPtr numérique
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
,decimal
oubool
. - 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
sbyte
versshort
,int
,nint
,long
,float
,double
oudecimal
. - De
byte
versshort
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,float
,double
oudecimal
. - De
short
versint
,nint
,long
,float
,double
oudecimal
. - De
ushort
versint
,uint
,nint
,nuint
,long
,ulong
,float
,double
oudecimal
. - De
int
versnint
,long
,float
,double
oudecimal
. - De
uint
versnuint
,long
,ulong
,float
,double
oudecimal
. - De
nint
verslong
,float
,double
oudecimal
. - De
nuint
versulong
,float
,double
oudecimal
. - De
long
versfloat
,double
oudecimal
. - De
ulong
versfloat
,double
oudecimal
. - De
char
versushort
,int
,uint
,nint
,nuint
,long
,ulong
,float
,double
oudecimal
. - De
float
versdouble
.
[...]
10.2.11 Conversions d’expressions constantes implicites
Une conversion d’expression constante implicite permet les conversions suivantes :
- Une constant_expression de type
int
peut être convertie en typesbyte
,byte
,short
,ushort
,uint
,nint
,nuint
ouulong
, à 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
sbyte
versbyte
,ushort
,uint
,nuint
,ulong
ouchar
. - De
byte
verssbyte
ouchar
. - De
short
verssbyte
,byte
,ushort
,uint
,nuint
,ulong
ouchar
. - De
ushort
verssbyte
,byte
,short
ouchar
. - De
int
verssbyte
,byte
,short
,ushort
,uint
,nuint
,ulong
ouchar
. - De
uint
verssbyte
,byte
,short
,ushort
,int
,nint
ouchar
. - De
long
verssbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,ulong
ouchar
. - De
nint
verssbyte
,byte
,short
,ushort
,int
,uint
,nuint
,ulong
ouchar
. - De
nuint
verssbyte
,byte
,short
,ushort
,int
,uint
,nint
,long
ouchar
. - De
ulong
verssbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
ouchar
. - De
char
verssbyte
,byte
oushort
. - De
float
verssbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
oudecimal
. - De
double
verssbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
,float
oudecimal
. - De
decimal
verssbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
,float
oudouble
.
[...]
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
,double
oudecimal
vers n’importe quel enum_type. - De n’importe quel enum_type vers
sbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
,float
,double
oudecimal
. - 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éplacex
vers la droite d'un nombre de bits calculé comme décrit ci-dessous.Lorsque
x
est de typeint
,nint
oulong
, les bits de poids faible dex
sont 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 six
est non négatif, et mises à un six
est négatif.Lorsque
x
est de typeuint
,nuint
ouulong
, les bits de poids faible dex
sont 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
x
estnint
ounuint
, le décalage est déterminé par les cinq bits de poids faible decount
sur une plateforme 32 bits, ou les six bits de poids faible decount
sur 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
,long
ouulong
vers n’importe quel pointer_type. - De n’importe quel pointer_type vers
sbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
ouulong
.
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 + int
IntPtr - int
IntPtr -> int
long -> IntPtr
void* -> 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