共用方式為


數值型 IntPtr

注意

本文是功能規格。 規格可作為功能的設計檔。 其中包含建議的規格變更,以及功能設計和開發期間所需的資訊。 這些文章會發佈,直到提議的規格變更完成並併併入目前的ECMA規格為止。

功能規格與已完成實作之間可能有一些差異。 這些差異是在的相關 語言設計會議(LDM)會議紀錄中擷取的。

您可以在 規範的文章中深入瞭解將功能規範納入 C# 語言標準的過程。

總結

這是初始原生整數特徵的修訂(規格),其中 nint/nuint 類型與基礎類型不同 System.IntPtr/System.UIntPtr。 簡言之,我們現在會將 nint/nuint 視為簡單類型別名 System.IntPtr/System.UIntPtr,就像 intSystem.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 整數類型:sbytebyteshortushortintuintnintnuintlongulongchar。 [...]

8.8 非受控類型

換句話說,unmanaged_type 是下列之一:

  • sbytebyteshortushortintuintnintnuintlongulongcharfloatdoubledecimalbool
  • 任何 enum_type
  • 任何使用者定義 struct_type 不是建構的類型,且只包含 unmanaged_type的字段。
  • 在不安全的程式碼中,任何 pointer_type

10.2.3 隱含數值轉換

隱含數值轉換如下:

  • sbyteshortintnintlongfloatdoubledecimal
  • byteshortushortintuintnintnuintlongulongfloatdoubledecimal
  • shortintnintlongfloatdoubledecimal
  • ushortintuintnintnuintlongulongfloatdoubledecimal
  • intnintlongfloatdoubledecimal
  • uintnuintlongulongfloatdoubledecimal
  • nintlongfloatdoubledecimal
  • nuintulongfloatdoubledecimal
  • longfloatdoubledecimal
  • ulongfloatdoubledecimal
  • charushortintuintnintnuintlongulongfloatdoubledecimal
  • floatdouble

[...]

10.2.11 隱含常數表達式轉換

隱含常數表示式轉換允許下列轉換:

  • int 類型的 constant_expression 可以轉換成類型 sbytebyteshortushortuintnintnuintulong,前提是 constant_expression 的值在目的類型範圍內。 [...]

10.3.2 明確數值轉換

明確數值轉換是從 numeric_type 轉換成另一個隱含數值轉換不存在的另一個 numeric_type

  • sbytebyteushortuintnuintulongchar
  • bytesbytechar
  • shortsbytebyteushortuintnuintulongchar
  • ushortsbytebyteshortchar
  • intsbytebyteshortushortuintnuintulongchar
  • uintsbytebyteshortushortintnintchar
  • longsbytebyteshortushortintuintnintnuintulongchar
  • nintsbytebyteshortushortintuintnuintulongchar
  • nuintsbytebyteshortushortintuintnintlongchar
  • ulongsbytebyteshortushortintuintnintnuintlongchar
  • charsbytebyteshort
  • floatsbytebyteshortushortintuintnintnuintlongulongchardecimal
  • doublesbytebyteshortushortintuintnintnuintlongulongcharfloatdecimal
  • decimalsbytebyteshortushortintuintnintnuintlongulongcharfloatdouble

[...]

10.3.3 明確列舉轉換

明確的列舉轉換有如下幾種:

  • sbytebyteshortushortintuintnintnuintlongulongcharfloatdoubledecimal 轉換到任何 之 enum_type
  • 從任何 enum_typesbytebyteshortushortintuintnintnuintlongulongcharfloatdoubledecimal
  • 從任何 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的等級相同,而且每個表達式的類型應為 intuintnintnuintlongulong, 或隱含轉換成其中一或多個類型。

11.8.12.2 陣組存取

[...]argument_list 中的運算式數目應與 array_type的等級相同,而且每個表達式的類型應為 intuintnintnuintlongulong, 或隱含轉換成其中一或多個類型。

[...]表單 P[A]的陣列記憶體取的運行時間處理,其中 Parray_typeprimary_no_array_creation_expression,而 Aargument_list,包含下列步驟: [...]

  • argument_list 的索引表達式會依左至右的順序進行評估。 在評估每個索引表示式之後,會執行下列其中一種類型的隱含轉換:intuintnintnuintlongulong。 在此清單中,選擇有隱含轉換存在的第一個類型。 [...]

12.8.16 後置遞增和遞減運算符

一元運算子超載解析用於選擇特定的運算子實作。 下列類型存在預先定義的 ++-- 運算符:sbytebyteshortushortintuintnintnuintlongulongcharfloatdoubledecimal及任何列舉類型。

12.9.2 一元加號運算符

預先定義的一元加運算符如下:

...
nint operator +(nint x);
nuint operator +(nuint x);

12.9.3 一元減號運算符

預先定義的一元減號運算符如下:

  • 整數否定:

    ...
    nint operator –(nint x);
    

12.8.16 後置遞增和遞減運算符

下列類型有預先定義的 ++-- 運算符:sbytebyteshortushortintuintnintnuintlongulongcharfloatdoubledecimal及任何列舉類型。

11.7.19 預設值表達式

此外,如果類型是下列其中一個實值型別,default_value_expression 是常數表達式:sbytebyteshortushortintuintnintnuintlongulongcharfloatdoubledecimalbool, 或任何列舉型別。

12.9.5 位補碼運算符

預先定義的位補碼運算符如下:

...
nint operator ~(nint x);
nuint operator ~(nuint x);

12.9.6 前置詞遞增和遞減運算符

下列類型有預先定義的 ++-- 運算符:sbytebyteshortushortintuintnintnuintlongulongcharfloatdoubledecimal及任何列舉類型。

12.10 算術運算元

12.10.2 乘法運算符

預先定義的乘法運算符如下所列。 運算子都會計算 xy的乘積。

  • 整數乘法:

    ...
    nint operator *(nint x, nint y);
    nuint operator *(nuint x, nuint y);
    

12.10.3 除法運算符

預先定義的除法運算符如下所列。 所有運算元都會計算 xy的商數。

  • 整數除法:

    ...
    nint operator /(nint x, nint y);
    nuint operator /(nuint x, nuint y);
    

12.10.4 餘數運算符

預先定義的餘數運算符如下所列。 運算子都會計算 xy之間除法的餘數。

  • 整數餘數:

    ...
    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 的類型為 intnintlong時,會捨棄 x 低階位,其餘位會向右移位,如果 x 為非負數,則會將高階空白位位置設定為零,如果 x 為負數,則會設定為 1。

    x 類型為 uintnuintulong時,會捨棄 x 低階位,其餘位會向右移位,而高階空白位位置會設定為零。

  • 無符號右移:

    ...
    nint operator >>>(nint x, int count);
    nuint operator >>>(nuint x, int count);
    

針對預先定義的運算符,要移位的位數會計算如下: [...]

  • x 的類型是 nintnuint時,移位計數由 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 常數表達式

常數表達式可以是實值型別或參考型別。 如果常數表達式是實值型別,它必須是下列其中一種類型:sbytebyteshortushortintuintnintnuintlongulongcharfloatdoubledecimalbool, 或任何列舉型別。

[...]

隱含常數表達式轉換允許類型 int 常數表達式轉換成 sbytebyteshortushortuintnintnuintulong,前提是常數表達式的值在目的型別的範圍內。

17.4 陣列元素存取

數位元素是使用表單 A[I₁, I₂, ..., Iₓ]element_access 表示式來存取,其中 A 是陣列類型的運算式,而每個 Iₑ 都是類型 intuintnintnuintlongulong或可以隱含轉換成其中一或多個類型的表達式。 陣列專案存取的結果是變數,也就是索引所選取的陣列專案。

23.5 指標轉換

23.5.1 一般

[...]

此外,在不安全的情境中,可用的明確轉換集合會擴充,以包含下列明確的指標轉換:

  • 從任何 pointer_type 到任何其他 pointer_type
  • sbytebyteshortushortintuintnintnuintlongulong 到任何 pointer_type
  • 從任何 pointer_typesbytebyteshortushortintuintnintnuintlongulong

23.6.4 指標元素存取

在形式 P[E]的指標元素存取中,P 應為指標型別而非 void*的表達式,而 E 應為可以被隱式轉換為 intuintnintnuintlongulong的表達式。

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);

假設指標類型的表達式 PT*,以及類型為 intuintnintnuintlongulongN 表達式,表達式 P + NN + P 計算類型 T* 的指標值,其結果就是將 N * sizeof(T) 新增至 P指定的位址。 同樣地,表達式 P – N 會計算出從 P指定的位址中減去 N * sizeof(T) 所得到的類型 T* 的指標值。

各種考慮

重大變更

此設計的主要影響之一是 System.IntPtrSystem.UIntPtr 獲得一些內建運算元(轉換、一元和二進位)。
這些運算子包括 checked 運算子,這表示這些類型的下列運算子現在會在溢位時擲回:

  • IntPtr + int
  • IntPtr - int
  • IntPtr -> int
  • long -> IntPtr
  • void* -> IntPtr

元數據編碼

此設計意味著,nintnuint 可以簡單地發射為 System.IntPtrSystem.UIntPtr,無需使用 System.Runtime.CompilerServices.NativeIntegerAttribute
同樣地,載入元數據時 NativeIntegerAttribute 可以忽略。