IntPtr numerico
Nota
Questo articolo è una specifica di funzionalità. La specifica funge da documento di progettazione per la funzionalità. Include le modifiche specifiche proposte, insieme alle informazioni necessarie durante la progettazione e lo sviluppo della funzionalità. Questi articoli vengono pubblicati fino a quando le modifiche specifiche proposte non vengono completate e incorporate nella specifica ECMA corrente.
Potrebbero verificarsi alcune discrepanze tra la specifica di funzionalità e l'implementazione completata. Tali differenze vengono acquisite nelle note
Ulteriori informazioni sul processo di adozione degli speclet delle funzionalità nello standard del linguaggio C# sono disponibili nell'articolo sulle specifiche di .
Sommario
Si tratta di una revisione della funzionalità iniziale dei numeri interi nativi (specifica), in cui i tipi di nint
/nuint
erano distinti dai tipi sottostanti System.IntPtr
/System.UIntPtr
.
In breve, ora trattiamo nint
/nuint
come semplici tipi alias di System.IntPtr
/System.UIntPtr
, come facciamo per int
in relazione a System.Int32
. Il flag di funzionalità di runtime System.Runtime.CompilerServices.RuntimeFeature.NumericIntPtr
attiva questo nuovo comportamento.
Disegno
8.3.5 Tipi semplici
C# fornisce un set di tipi di struct
predefiniti denominati tipi semplici. I tipi semplici vengono identificati tramite parole chiave, ma queste parole chiave sono semplicemente alias per i tipi di struct
predefiniti nello spazio dei nomi System
, come descritto nella tabella seguente.
parola-chiave | tipo con 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 Tipi integrali
C# supporta undici tipi integrali: sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, long
, ulong
e char
. [...]
8.8 Tipi non gestiti
In altre parole, un unmanaged_type è uno dei seguenti:
-
sbyte
,byte
,short
,ushort
,int
,uint
, ,nint
,nuint
,,long
,ulong
,char
,float
,double
,decimal
obool
. - Qualsiasi enum_type.
- Qualsiasi struct_type definita dall'utente che non è un tipo composto e contiene solo campi di unmanaged_type.
- Nel codice non sicuro, qualsiasi pointer_type.
10.2.3 Conversioni numeriche implicite
Le conversioni numeriche implicite sono:
- Da
sbyte
ashort
,int
,nint
,long
,float
,double
odecimal
. - Da
byte
ashort
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,float
,double
odecimal
. - Da
short
aint
,nint
,long
,float
,double
odecimal
. - Da
ushort
aint
,uint
,nint
,nuint
,long
,ulong
,float
,double
odecimal
. - Da
int
anint
,long
,float
,double
odecimal
. - Da
uint
anuint
,long
,ulong
,float
,double
odecimal
. -
Da
nint
along
,float
,double
odecimal
. -
Da
nuint
aulong
,float
,double
odecimal
. - Da
long
afloat
,double
odecimal
. - Da
ulong
afloat
,double
odecimal
. - Da
char
aushort
,int
,uint
,nint
,nuint
,long
,ulong
,float
,double
odecimal
. - Da
float
adouble
.
[...]
10.2.11 Conversioni implicite di espressioni costanti
Una conversione implicita di espressioni costanti consente le conversioni seguenti:
- Un constant_expression di tipo
int
può essere convertito nel tiposbyte
,byte
,short
,ushort
,uint
,nint
,nuint
oulong
, purché il valore del constant_expression sia compreso nell'intervallo del tipo di destinazione. [...]
10.3.2 Conversioni numeriche esplicite
Le conversioni numeriche esplicite sono le conversioni da un numeric_type a un'altra numeric_type per cui non esiste già una conversione numerica implicita:
- Da
sbyte
abyte
,ushort
,uint
,nuint
,ulong
ochar
. - Da
byte
asbyte
ochar
. - Da
short
asbyte
,byte
,ushort
,uint
,nuint
,ulong
ochar
. - Da
ushort
asbyte
,byte
,short
ochar
. - Da
int
asbyte
,byte
,short
,ushort
,uint
,nuint
,ulong
ochar
. - Da
uint
asbyte
,byte
,short
,ushort
,int
,nint
ochar
. - Da
long
asbyte
,byte
,short
,ushort
,int
,uint
, ,nint
,nuint
,,ulong
ochar
. -
Da
nint
asbyte
,byte
,short
,ushort
,int
,uint
,nuint
,ulong
ochar
. -
Da
nuint
asbyte
,byte
,short
,ushort
,int
,uint
,nint
,long
ochar
. - Da
ulong
asbyte
,byte
,short
,ushort
,int
,uint
, ,nint
,nuint
,,long
ochar
. - Da
char
asbyte
,byte
oshort
. - Da
float
asbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
odecimal
. - Da
double
asbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
,float
odecimal
. - Da
decimal
asbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
,float
odouble
.
[...]
10.3.3 Conversioni esplicite di enumerazione
Le conversioni esplicite di enumerazione sono:
- Da
sbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
,float
,double
odecimal
a qualsiasi enum_type. - Da qualsiasi enum_type a
sbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
,float
,double
odecimal
. - Da qualunque enum_type a qualunque altro enum_type.
12.6.4.7 Destinazione di conversione migliore
Dato due tipi T₁
e T₂
, T₁
è una destinazione di conversione migliore rispetto a T₂
se uno dei blocchi seguenti:
- Esiste una conversione implicita da
T₁
aT₂
e non esiste alcuna conversione implicita daT₂
aT₁
-
T₁
èTask<S₁>
,T₂
èTask<S₂>
eS₁
è una destinazione di conversione migliore rispetto aS₂
-
T₁
èS₁
oS₁?
in cuiS₁
è un tipo integrale con segno eT₂
èS₂
oS₂?
doveS₂
è un tipo integrale senza segno. In particolare: [...]
12.8.12 Accesso all'elemento
[...] Il numero di espressioni nella argument_list deve essere uguale al rango del array_typee ogni espressione deve essere di tipo int
, uint
, nint
, nuint
, long
, o ulong,
o deve essere implicitamente convertibile in uno o più di questi tipi.
11.8.12.2 Accesso alla matrice
[...] Il numero di espressioni nella argument_list deve essere uguale al rango del array_typee ogni espressione deve essere di tipo int
, uint
, nint
, nuint
, long
, o ulong,
o deve essere implicitamente convertibile in uno o più di questi tipi.
[...] L'elaborazione in fase di esecuzione di un accesso di matrice alla forma P[A]
, dove P
è un primary_no_array_creation_expression di un array_type e A
è un argument_list, è costituita dai passaggi seguenti: [...]
- Le espressioni di indice del argument_list vengono valutate in ordine, da sinistra a destra. Dopo la valutazione di ogni espressione di indice, viene eseguita una conversione implicita in uno dei tipi seguenti:
int
,uint
,nint
,nuint
,long
,ulong
. Viene scelto il primo tipo in questo elenco per il quale esiste una conversione implicita. [...]
12.8.16 Operatori di incremento e decremento postfissi
La risoluzione dell'overload di un operatore unario viene applicata per selezionare una specifica implementazione dell'operatore. Esistono operatori predefiniti ++
e --
per i tipi seguenti: sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
,long
, ulong
, char
, float
, double
, decimal
e qualsiasi tipo di enumerazione.
Operatore 12.9.2 Unary plus
Gli operatori unari più predefiniti sono:
...
nint operator +(nint x);
nuint operator +(nuint x);
12.9.3 Operatore unario meno
Gli operatori unari meno predefiniti sono:
Negazione integer:
... nint operator –(nint x);
12.8.16 Operatori di incremento e decremento postfissi
Esistono operatori predefiniti ++
e --
per i tipi seguenti: sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, long
, ulong
, char
, float
, double
, decimal
e qualsiasi tipo di enumerazione.
11.7.19 Espressioni di valore predefinite
Inoltre, un default_value_expression è un'espressione costante se il tipo è uno dei tipi di valore seguenti: sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, long
, ulong
, char
, float
, double
, decimal
, bool,
o qualsiasi tipo di enumerazione.
12.9.5 Operatore di complemento bit per bit
Gli operatori di complemento bit per bit predefiniti sono:
...
nint operator ~(nint x);
nuint operator ~(nuint x);
12.9.6 Operatori di incremento e decremento del prefisso
Esistono operatori predefiniti ++
e --
per i tipi seguenti: sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, long
, ulong
, char
, float
, double
, decimal
e qualsiasi tipo di enumerazione.
12.10 Operatori aritmetici
Operatore di moltiplicazione 12.10.2
Di seguito sono elencati gli operatori di moltiplicazione predefiniti. Tutti gli operatori calcolano il prodotto di x
e y
.
Moltiplicazione di numeri interi:
... nint operator *(nint x, nint y); nuint operator *(nuint x, nuint y);
Operatore di divisione 12.10.3
Di seguito sono elencati gli operatori di divisione predefiniti. Tutti gli operatori calcolano il quoziente di x
e y
.
Divisione integer:
... nint operator /(nint x, nint y); nuint operator /(nuint x, nuint y);
12.10.4 Operatore di resto
Di seguito sono elencati gli operatori di resto predefiniti. Tutti gli operatori calcolano il resto della divisione tra x
e y
.
Resto intero:
... nint operator %(nint x, nint y); nuint operator %(nuint x, nuint y);
12.10.5 Operatore di somma
Addizione di numeri interi:
... nint operator +(nint x, nint y); nuint operator +(nuint x, nuint y);
12.10.6 Operatore di sottrazione
Sottrazione integer:
... nint operator –(nint x, nint y); nuint operator –(nuint x, nuint y);
12.11 Operatori shift
Di seguito sono elencati gli operatori di spostamento predefiniti.
Sposta a sinistra:
... nint operator <<(nint x, int count); nuint operator <<(nuint x, int count);
Sposta a destra
... nint operator >>(nint x, int count); nuint operator >>(nuint x, int count);
L'operatore
>>
spostax
a destra di un numero di bit calcolato come descritto di seguito.Quando
x
è di tipoint
,nint
olong
, i bit di ordine ridotto dix
vengono rimossi, i bit rimanenti vengono spostati verso destra e le posizioni di bit vuote dell'ordine elevato vengono impostate su zero sex
è non negativo e impostato su uno sex
è negativo.Quando
x
è di tipouint
,nuint
oulong
, i bit di ordine ridotto dix
vengono rimossi, i bit rimanenti vengono spostati verso destra e le posizioni dei bit vuoti dell'ordine elevato vengono impostate su zero.Spostamento senza segno a destra:
... nint operator >>>(nint x, int count); nuint operator >>>(nuint x, int count);
Per gli operatori predefiniti, il numero di bit da spostare viene calcolato nel modo seguente: [...]
- Quando il tipo di
x
ènint
onuint
, il conteggio dello spostamento è determinato dai cinque bit meno significativi dicount
su una piattaforma a 32 bit, oppure dai sei bit meno significativi dicount
su una piattaforma a 64 bit.
12.12 Operatori relazionali e di test dei tipi
12.12.2 Operatori di confronto integer
Gli operatori di confronto integer predefiniti sono:
...
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 Operatori logici
12.12.2 Operatori logici Integer
Gli operatori logici integer predefiniti sono:
...
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 Espressioni costanti
Un'espressione costante può essere un tipo valore o un tipo riferimento. Se un'espressione costante è un tipo valore, deve essere uno dei tipi seguenti: sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, long
, ulong
, char
, float
, double
, decimal
, bool,
o qualsiasi tipo di enumerazione.
[...]
Una conversione implicita di espressioni costanti consente la conversione di un'espressione costante di tipo int
in sbyte
, byte
, short
, ushort
, uint
, nint
, nuint
, o ulong
, purché il valore dell'espressione costante sia compreso nell'intervallo del tipo di destinazione.
17.4 Accesso agli elementi di un array
È possibile accedere agli elementi di matrice usando element_access espressioni del form A[I₁, I₂, ..., Iₓ]
, dove A
è un'espressione di un tipo di matrice e ogni Iₑ
è un'espressione di tipo int
, uint
, nint
, nuint
,long
, ulong
o può essere convertita in modo implicito in uno o più di questi tipi. Il risultato dell'accesso a un elemento di matrice è una variabile, ovvero l'elemento della matrice selezionato dagli indici.
23.5 Conversioni dei puntatori
23.5.1 Generale
[...]
Inoltre, in un contesto non sicuro, il set di conversioni esplicite disponibili viene esteso per includere le seguenti conversioni esplicite di puntatore:
- Da qualsiasi pointer_type a qualsiasi altro pointer_type.
- Da
sbyte
,byte
,short
,ushort
,int
,uint
, ,nint
,nuint
,,long
oulong
a qualsiasi pointer_type. - Da qualsiasi pointer_type a
sbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
oulong
.
23.6.4 Accesso all'elemento puntatore
In un accesso a un elemento puntatore del tipo P[E]
, P
deve essere un'espressione di tipo puntatore diverso da void*
e E
deve essere un'espressione che può essere convertita in modo implicito in int
, uint
, nint
, nuint
,long
o ulong
.
23.6.7 Aritmetica del puntatore
In un contesto non sicuro, l'operatore +
e l'operatore –
possono essere applicati ai valori di tutti i tipi di puntatore tranne void*
. Di conseguenza, per ogni tipo di puntatore T*
, gli operatori seguenti vengono definiti in modo implicito:
[...]
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);
Data un'espressione P
di un tipo puntatore T*
e un'espressione N
di tipo int
, uint
, nint
, nuint
,long
o ulong
, le espressioni P + N
e N + P
calcolano il valore del puntatore di tipo T*
risultante dall'aggiunta di N * sizeof(T)
all'indirizzo specificato da P
. Analogamente, l'espressione P – N
calcola il valore del puntatore di tipo T*
risultante dalla sottrazione di N * sizeof(T)
dall'indirizzo specificato da P
.
Varie considerazioni
Modifiche di rilievo
Uno degli effetti principali di questo design è che System.IntPtr
e System.UIntPtr
ottengono alcuni operatori incorporati (conversioni, unari e binari).
Tali operatori includono gli operatori checked
, il che significa che gli operatori seguenti su tali tipi ora genereranno un'eccezione in caso di overflow:
IntPtr + int
IntPtr - int
IntPtr -> int
long -> IntPtr
void* -> IntPtr
Codifica dei metadati
Questo design significa che nint
e nuint
possono essere semplicemente generati come System.IntPtr
e System.UIntPtr
, senza l'uso di System.Runtime.CompilerServices.NativeIntegerAttribute
.
Allo stesso modo, caricando i metadati, si può ignorare NativeIntegerAttribute
.
C# feature specifications