數值型 IntPtr
注意
本文是功能規格。 規格可作為功能的設計檔。 其中包含建議的規格變更,以及功能設計和開發期間所需的資訊。 這些文章會發佈,直到提議的規格變更完成並併併入目前的ECMA規格為止。
功能規格與已完成實作之間可能有一些差異。 這些差異是在的相關
您可以在 規範的文章中深入瞭解將功能規範納入 C# 語言標準的過程。
總結
這是初始原生整數特徵的修訂(規格),其中 nint
/nuint
類型與基礎類型不同 System.IntPtr
/System.UIntPtr
。
簡言之,我們現在會將 nint
/nuint
視為簡單類型別名 System.IntPtr
/System.UIntPtr
,就像 int
與 System.Int32
相關時一樣。
System.Runtime.CompilerServices.RuntimeFeature.NumericIntPtr
運行時間功能旗標會觸發這個新行為。
設計
8.3.5 簡單類型
C# 提供一組預先定義的 struct
類型,稱為簡單型別。 簡單類型是透過關鍵詞來識別,但這些關鍵詞只是 System
命名空間中預先定義 struct
類型的別名,如下表所述。
關鍵詞 | 別名類型 |
---|---|
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 整數類型
C# 支援 11 整數類型:sbyte
、byte
、short
、ushort
、int
、uint
、nint
、nuint
、long
、ulong
和 char
。 [...]
8.8 非受控類型
換句話說,unmanaged_type 是下列之一:
-
sbyte
、byte
、short
、ushort
、int
、uint
、nint
、nuint
、long
、ulong
、char
、float
、double
、decimal
或bool
。 - 任何 enum_type。
- 任何使用者定義 struct_type 不是建構的類型,且只包含 unmanaged_type的字段。
- 在不安全的程式碼中,任何 pointer_type。
10.2.3 隱含數值轉換
隱含數值轉換如下:
- 從
sbyte
到short
、int
、nint
、long
、float
、double
或decimal
。 - 從
byte
到short
、ushort
、int
、uint
、nint
、nuint
、long
、ulong
、float
、double
或decimal
。 - 從
short
到int
、nint
、long
、float
、double
或decimal
。 - 從
ushort
到int
、uint
、nint
、nuint
、long
、ulong
、float
、double
或decimal
。 - 從
int
到nint
、long
、float
、double
或decimal
。 - 從
uint
到nuint
、long
、ulong
、float
、double
或decimal
。 -
從
nint
到long
、float
、double
或decimal
。 -
從
nuint
到ulong
、float
、double
或decimal
。 - 從
long
到float
、double
或decimal
。 - 從
ulong
到float
、double
或decimal
。 - 從
char
到ushort
、int
、uint
、nint
、nuint
、long
、ulong
、float
、double
或decimal
。 - 從
float
到double
。
[...]
10.2.11 隱含常數表達式轉換
隱含常數表示式轉換允許下列轉換:
-
int
類型的 constant_expression 可以轉換成類型sbyte
、byte
、short
、ushort
、uint
、nint
、nuint
或ulong
,前提是 constant_expression 的值在目的類型範圍內。 [...]
10.3.2 明確數值轉換
明確數值轉換是從 numeric_type 轉換成另一個隱含數值轉換不存在的另一個 numeric_type:
- 從
sbyte
到byte
、ushort
、uint
、nuint
、ulong
或char
。 - 從
byte
到sbyte
或char
。 - 從
short
到sbyte
、byte
、ushort
、uint
、nuint
、ulong
或char
。 - 從
ushort
到sbyte
、byte
、short
或char
。 - 從
int
到sbyte
、byte
、short
、ushort
、uint
、nuint
、ulong
或char
。 - 從
uint
到sbyte
、byte
、short
、ushort
、int
、nint
或char
。 - 從
long
到sbyte
、byte
、short
、ushort
、int
、uint
、nint
、nuint
、ulong
或char
。 -
從
nint
到sbyte
、byte
、short
、ushort
、int
、uint
、nuint
、ulong
或char
。 -
從
nuint
到sbyte
、byte
、short
、ushort
、int
、uint
、nint
、long
或char
。 - 從
ulong
到sbyte
、byte
、short
、ushort
、int
、uint
、nint
、nuint
、long
或char
。 - 從
char
到sbyte
、byte
或short
。 - 從
float
到sbyte
、byte
、short
、ushort
、int
、uint
、nint
、nuint
、long
、ulong
、char
或decimal
。 - 從
double
到sbyte
、byte
、short
、ushort
、int
、uint
、nint
、nuint
、long
、ulong
、char
、float
或decimal
。 - 從
decimal
到sbyte
、byte
、short
、ushort
、int
、uint
、nint
、nuint
、long
、ulong
、char
、float
或double
。
[...]
10.3.3 明確列舉轉換
明確的列舉轉換有如下幾種:
- 從
sbyte
、byte
、short
、ushort
、int
、uint
、、nint
、nuint
、、long
、ulong
、char
、float
、double
或decimal
轉換到任何 之 enum_type。 - 從任何 enum_type 到
sbyte
、byte
、short
、ushort
、int
、uint
、nint
、nuint
、long
、ulong
、char
、float
、double
或decimal
。 - 從任何 enum_type 到任何其他 enum_type。
12.6.4.7 更好的轉換目標
假設有兩種類型 T₁
和 T₂
,如果下列其中一項保留,T₁
是 比 T₂
更好的轉換 目標:
- 存在從
T₁
到T₂
的隱含轉換,而且不存在從T₂
到T₁
的隱含轉換 -
T₁
是Task<S₁>
、T₂
Task<S₂>
,而S₁
是比S₂
更好的轉換目標 -
T₁
是S₁
或S₁?
,其中S₁
是帶正負號整數型別,T₂
是S₂
或S₂?
,其中S₂
是無符號整數型別。 具體來說: [...]
12.8.12 元素存取
[...]argument_list 中的運算式數目應與 array_type的等級相同,而且每個表達式的類型應為 int
、uint
、nint
、nuint
、long
、ulong,
或隱含轉換成其中一或多個類型。
11.8.12.2 陣組存取
[...]argument_list 中的運算式數目應與 array_type的等級相同,而且每個表達式的類型應為 int
、uint
、nint
、nuint
、long
、ulong,
或隱含轉換成其中一或多個類型。
[...]表單 P[A]
的陣列記憶體取的運行時間處理,其中 P
是 array_type 的 primary_no_array_creation_expression,而 A
是 argument_list,包含下列步驟: [...]
-
argument_list 的索引表達式會依左至右的順序進行評估。 在評估每個索引表示式之後,會執行下列其中一種類型的隱含轉換:
int
、uint
、nint
、nuint
、long
、ulong
。 在此清單中,選擇有隱含轉換存在的第一個類型。 [...]
12.8.16 後置遞增和遞減運算符
一元運算子超載解析用於選擇特定的運算子實作。 下列類型存在預先定義的 ++
和 --
運算符:sbyte
、byte
、short
、ushort
、int
、uint
、nint
、nuint
、long
、ulong
、char
、float
、double
、decimal
及任何列舉類型。
12.9.2 一元加號運算符
預先定義的一元加運算符如下:
...
nint operator +(nint x);
nuint operator +(nuint x);
12.9.3 一元減號運算符
預先定義的一元減號運算符如下:
整數否定:
... nint operator –(nint x);
12.8.16 後置遞增和遞減運算符
下列類型有預先定義的 ++
和 --
運算符:sbyte
、byte
、short
、ushort
、int
、uint
、nint
、nuint
、long
、ulong
、char
、float
、double
、decimal
及任何列舉類型。
11.7.19 預設值表達式
此外,如果類型是下列其中一個實值型別,default_value_expression 是常數表達式:sbyte
、byte
、short
、ushort
、int
、uint
nint
、nuint
、long
、ulong
、char
、float
、double
、decimal
、bool,
或任何列舉型別。
12.9.5 位補碼運算符
預先定義的位補碼運算符如下:
...
nint operator ~(nint x);
nuint operator ~(nuint x);
12.9.6 前置詞遞增和遞減運算符
下列類型有預先定義的 ++
和 --
運算符:sbyte
、byte
、short
、ushort
、int
、uint
、nint
、nuint
、long
、ulong
、char
、float
、double
、decimal
及任何列舉類型。
12.10 算術運算元
12.10.2 乘法運算符
預先定義的乘法運算符如下所列。 運算子都會計算 x
和 y
的乘積。
整數乘法:
... nint operator *(nint x, nint y); nuint operator *(nuint x, nuint y);
12.10.3 除法運算符
預先定義的除法運算符如下所列。 所有運算元都會計算 x
和 y
的商數。
整數除法:
... nint operator /(nint x, nint y); nuint operator /(nuint x, nuint y);
12.10.4 餘數運算符
預先定義的餘數運算符如下所列。 運算子都會計算 x
與 y
之間除法的餘數。
整數餘數:
... nint operator %(nint x, nint y); nuint operator %(nuint x, nuint y);
12.10.5 加法運算符
整數加法:
... nint operator +(nint x, nint y); nuint operator +(nuint x, nuint y);
12.10.6 減法運算符
整數減法:
... nint operator –(nint x, nint y); nuint operator –(nuint x, nuint y);
12.11 位移運算子
預先定義的移位運算符如下所列。
左移:
... nint operator <<(nint x, int count); nuint operator <<(nuint x, int count);
右移:
... nint operator >>(nint x, int count); nuint operator >>(nuint x, int count);
>>
運算子會將x
根據以下描述的位元數向右移位。當
x
的類型為int
、nint
或long
時,會捨棄x
低階位,其餘位會向右移位,如果x
為非負數,則會將高階空白位位置設定為零,如果x
為負數,則會設定為 1。當
x
類型為uint
、nuint
或ulong
時,會捨棄x
低階位,其餘位會向右移位,而高階空白位位置會設定為零。無符號右移:
... nint operator >>>(nint x, int count); nuint operator >>>(nuint x, int count);
針對預先定義的運算符,要移位的位數會計算如下: [...]
- 當
x
的類型是nint
或nuint
時,移位計數由 32 位元平台上的低位五位count
或 64 位元平台上的低位六位count
確定。
12.12 關係型和型別測試運算符
12.12.2 整數比較運算符
預先定義的整數比較運算符如下:
...
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 邏輯運算符
12.12.2 整數邏輯運算符
預先定義的整數邏輯運算符如下:
...
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 常數表達式
常數表達式可以是實值型別或參考型別。 如果常數表達式是實值型別,它必須是下列其中一種類型:sbyte
、byte
、short
、ushort
、int
、uint
、nint
、nuint
、long
、ulong
、char
、float
、double
、decimal
、bool,
或任何列舉型別。
[...]
隱含常數表達式轉換允許類型 int
常數表達式轉換成 sbyte
、byte
、short
、ushort
、uint
、nint
、nuint
、 或 ulong
,前提是常數表達式的值在目的型別的範圍內。
17.4 陣列元素存取
數位元素是使用表單 A[I₁, I₂, ..., Iₓ]
的 element_access 表示式來存取,其中 A
是陣列類型的運算式,而每個 Iₑ
都是類型 int
、uint
、nint
、nuint
、long
、ulong
或可以隱含轉換成其中一或多個類型的表達式。 陣列專案存取的結果是變數,也就是索引所選取的陣列專案。
23.5 指標轉換
23.5.1 一般
[...]
此外,在不安全的情境中,可用的明確轉換集合會擴充,以包含下列明確的指標轉換:
- 從任何 pointer_type 到任何其他 pointer_type。
- 從
sbyte
、byte
、short
、ushort
、int
、uint
、nint
、nuint
、long
或ulong
到任何 pointer_type。 - 從任何 pointer_type 到
sbyte
、byte
、short
、ushort
、int
、uint
、nint
、nuint
、long
或ulong
。
23.6.4 指標元素存取
在形式 P[E]
的指標元素存取中,P
應為指標型別而非 void*
的表達式,而 E
應為可以被隱式轉換為 int
、uint
、nint
、nuint
、long
或 ulong
的表達式。
23.6.7 指標算術
在不安全的內容中,+
運算子和 –
運算符可以套用至除了 void*
以外的所有指標類型值。 因此,對於每個指標類型 T*
,會隱含定義下列運算符:
[...]
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);
假設指標類型的表達式 P
T*
,以及類型為 int
、uint
、nint
、nuint
、long
或 ulong
的 N
表達式,表達式 P + N
和 N + P
計算類型 T*
的指標值,其結果就是將 N * sizeof(T)
新增至 P
指定的位址。 同樣地,表達式 P – N
會計算出從 P
指定的位址中減去 N * sizeof(T)
所得到的類型 T*
的指標值。
各種考慮
重大變更
此設計的主要影響之一是 System.IntPtr
和 System.UIntPtr
獲得一些內建運算元(轉換、一元和二進位)。
這些運算子包括 checked
運算子,這表示這些類型的下列運算子現在會在溢位時擲回:
IntPtr + int
IntPtr - int
IntPtr -> int
long -> IntPtr
void* -> IntPtr
元數據編碼
此設計意味著,nint
和 nuint
可以簡單地發射為 System.IntPtr
和 System.UIntPtr
,無需使用 System.Runtime.CompilerServices.NativeIntegerAttribute
。
同樣地,載入元數據時 NativeIntegerAttribute
可以忽略。