数値 IntPtr
メモ
この記事は機能仕様についてです。 仕様は、機能の設計ドキュメントとして使用できます。 これには、提案された仕様の変更および機能の設計と開発時に必要な情報が含まれます。 これらの記事は、提案された仕様の変更が決定され、現在の ECMA 仕様に組み込まれるまで公開されます。
機能の仕様と行われた実装では、いくつかの違いがあることがあります。 これらの違いは、関連する言語設計ミーティング (LDM) メモに取り上げられています。
機能仕様を C# 言語標準に導入するプロセスの詳細については、仕様に関する記事を参照してください。
チャンピオンの課題: https://github.com/dotnet/csharplang/issues/6065
まとめ
これは、最初のネイティブ整数機能 (仕様) のリビジョンであり、nint
/nuint
型は基になる型 System.IntPtr
/System.UIntPtr
とは異なっていました。
つまり、nint
/nuint
は、System.Int32
に関連して int
のために行うように、System.IntPtr
/System.UIntPtr
をエイリアス化する単純な型として扱います。 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# では、sbyte
、byte
、short
、ushort
、int
、uint
、nint
、nuint
、long
、ulong
、char
の 7 つの整数型がサポートされています。 [...]
8.8 アンマネージ型
つまり、unmanaged_type は次のいずれかになります。
sbyte
,byte
,short
,ushort
,int
,uint
, ,nint
,nuint
,,long
,ulong
,char
,float
,double
,decimal
,bool
.- すべての enum_type。
- 構築型以外の、unmanaged_typeのフィールドのみを含む、ユーザー定義のすべての struct_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 は、constant_expressionの値が変換後の型の範囲内にある場合、型sbyte
、byte
、short
、ushort
、uint
、nint
、nuint
またはulong
に変換できます。 [...]
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₁
が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,
の型であるか、暗黙的にこれらの型の 1 つ以上に変換可能である必要があります。
11.8.12.2 配列へのアクセス
[...] argument_list 内の式の数は、 array_type のランクと同じである必要があります。各式は、int
uint
、nint
nuint
、long
、または ulong,
の型であるか、暗黙的にこれらの型の 1 つ以上に変換可能である必要があります。
形[...] 式 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
が負でない場合は空の上位ビット位置が 0 に設定され、x
が負の場合は 1 に設定されます。x
がuint
、nuint
、またはulong
の型の場合、x
の下位ビットは破棄され、残りのビットは右にシフトされ、上位の空のビット位置は 0 に設定されます。符号なしの右シフト:
... nint operator >>>(nint x, int count); nuint operator >>>(nuint x, int count);
定義済みの演算子の場合、シフトするビット数は次のように計算されます: [...]
x
の型がnint
またはnuint
の場合、シフト カウントは、32 ビット プラットフォームの下位 5 ビットのcount
、または 64 ビット プラットフォームの下位 6 ビットの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
であるか、これらの型の 1 つ以上に暗黙的に変換できます。 配列要素アクセスの結果は変数、つまりインデックスによって選択された配列要素です。
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*
と、型 N
、int
、nuint
、または long
の式 ulong
に基づき、P + N
と N + P
の式は、T*
によって指定されたアドレスに N * sizeof(T)
を加えた結果として得られる、型 P
のポインター値を計算します。 同様に、式 P – N
は、P
によって指定されたアドレスから N * sizeof(T)
を減算した型 T*
のポインター値を計算します。
さまざまな考慮事項
重大な変更
この設計の主な影響の 1 つは、System.IntPtr
と System.UIntPtr
が一部の組み込み演算子 (変換、単項、二項) を取得することです。
これには checked
演算子が含まれます。つまり、これらの型に対する次の演算子はオーバーフロー時にスローされます。
IntPtr + int
IntPtr - int
IntPtr -> int
long -> IntPtr
void* -> IntPtr
メタデータ エンコード
この設計は、nint
と nuint
が System.Runtime.CompilerServices.NativeIntegerAttribute
を使用せずに、単に System.IntPtr
および System.UIntPtr
として出力できることを意味します。
同様に、メタデータの読み込み時に NativeIntegerAttribute
を無視できます。
C# feature specifications