From 45a9e72e39510387a902cd34b0dc951da861fa8f Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 7 Mar 2026 12:21:46 -0500 Subject: [PATCH 1/4] Support Numeric IntPtr --- standard/unsafe-code.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/standard/unsafe-code.md b/standard/unsafe-code.md index 8b44374a7..f1b07bc42 100644 --- a/standard/unsafe-code.md +++ b/standard/unsafe-code.md @@ -787,14 +787,20 @@ In an unsafe context, the `+` operator ([§12.13.5](expressions.md#12135-additio ```csharp T* operator +(T* x, int y); T* operator +(T* x, uint y); +T* operator +(T* x, nint y); +T* operator +(T* x, nuint y); T* operator +(T* x, long y); T* operator +(T* x, ulong y); T* operator +(int x, T* y); T* operator +(uint x, T* y); +T* operator +(nint x, T* y); +T* operator +(nuint x, T* y); T* operator +(long x, T* y); T* operator +(ulong x, T* y); T* operator –(T* x, int y); T* operator –(T* x, uint y); +T* operator -(T* x, nint y); +T* operator -(T* x, nuint y); T* operator –(T* x, long y); T* operator –(T* x, ulong y); long operator –(T* x, T* y); @@ -802,7 +808,7 @@ long operator –(T* x, T* y); There are no predefined operators for pointer addition or subtraction with native integer ([§8.3.6](types.md#836-integral-types)) offsets. Instead, `nint` and `nuint` values shall be promoted to `long` and `ulong`, respectively, with pointer arithmetic using the predefined operators for those types. -Given an expression `P` of a data pointer type `T*` and an expression `N` of type `int`, `uint`, `long`, or `ulong`, the expressions `P + N` and `N + P` compute the pointer value of type `T*` that results from adding `N * sizeof(T)` to the address given by `P`. Likewise, the expression `P – N` computes the pointer value of type `T*` that results from subtracting `N * sizeof(T)` from the address given by `P`. +Given an expression `P` of a data pointer type `T*` and an expression `N` of type `int`, `uint`, `nint`, `nuint`, `long`, or `ulong`, the expressions `P + N` and `N + P` compute the pointer value of type `T*` that results from adding `N * sizeof(T)` to the address given by `P`. Likewise, the expression `P – N` computes the pointer value of type `T*` that results from subtracting `N * sizeof(T)` from the address given by `P`. Given two expressions, `P` and `Q`, of a data pointer type `T*`, the expression `P – Q` computes the difference between the addresses given by `P` and `Q` and then divides that difference by `sizeof(T)`. The type of the result is always `long`. In effect, `P - Q` is computed as `((long)(P) - (long)(Q)) / sizeof(T)`. From 1d8fc7ce0a43c8ab7d3d61e75dc4602cb03568fa Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 7 Mar 2026 12:35:54 -0500 Subject: [PATCH 2/4] Support Numeric IntPtr --- standard/expressions.md | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/standard/expressions.md b/standard/expressions.md index 82ce81a03..98443d427 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -287,6 +287,8 @@ As an example of numeric promotion, consider the predefined implementations of t ```csharp int operator *(int x, int y); uint operator *(uint x, uint y); +nint operator *(nint x, nint y); +nuint operator *(nuint x, nuint y); long operator *(long x, long y); ulong operator *(ulong x, ulong y); float operator *(float x, float y); @@ -298,8 +300,6 @@ When overload resolution rules ([§12.6.4](expressions.md#1264-overload-resoluti > *Example*: For the operation `b * s`, where `b` is a `byte` and `s` is a `short`, overload resolution selects `operator *(int, int)` as the best operator. Thus, the effect is that `b` and `s` are converted to `int`, and the type of the result is `int`. Likewise, for the operation `i * d`, where `i` is an `int` and `d` is a `double`, `overload` resolution selects `operator *(double, double)` as the best operator. *end example* -There are no predefined operators for dealing with native integer ([§8.3.6](types.md#836-integral-types)). Instead, `nint` and `nuint` values shall be promoted to `long` and `ulong`, respectively, and the resulting corresponding predefined operators used instead. - **End of informative text.** #### 12.4.7.2 Unary numeric promotions @@ -3733,6 +3733,8 @@ For an operation of the form `+x`, unary operator overload resolution ([§12.4. ```csharp int operator +(int x); uint operator +(uint x); +nint operator +(nint x); +nuint operator +(nuint x); long operator +(long x); ulong operator +(ulong x); float operator +(float x); @@ -3752,6 +3754,7 @@ For an operation of the form `–x`, unary operator overload resolution ([§12. ```csharp int operator –(int x); + nint operator –(nint x); long operator –(long x); ``` @@ -3801,6 +3804,8 @@ For an operation of the form `~x`, unary operator overload resolution ([§12.4.4 ```csharp int operator ~(int x); uint operator ~(uint x); +nint operator ~(nint x); +nuint operator ~(nuint x); long operator ~(long x); ulong operator ~(ulong x); ``` @@ -4146,6 +4151,8 @@ The predefined multiplication operators are listed below. The operators all comp ```csharp int operator *(int x, int y); uint operator *(uint x, uint y); + nint operator *(nint x, nint y); + nuint operator *(nuint x, nuint y); long operator *(long x, long y); ulong operator *(ulong x, ulong y); ``` @@ -4193,6 +4200,8 @@ The predefined division operators are listed below. The operators all compute th ```csharp int operator /(int x, int y); uint operator /(uint x, uint y); + nint operator /(nint x, nint y); + nuint operator /(nuint x, nuint y); long operator /(long x, long y); ulong operator /(ulong x, ulong y); ``` @@ -4244,6 +4253,8 @@ The predefined remainder operators are listed below. The operators all compute t ```csharp int operator %(int x, int y); uint operator %(uint x, uint y); + nint operator %(nint x, nint y); + nuint operator %(nuint x, nuint y); long operator %(long x, long y); ulong operator %(ulong x, ulong y); ``` @@ -4294,6 +4305,8 @@ The predefined addition operators are listed below. For numeric and enumeration ```csharp int operator +(int x, int y); uint operator +(uint x, uint y); + nint operator +(nint x, nint y); + nuint operator +(nuint x, nuint y); long operator +(long x, long y); ulong operator +(ulong x, ulong y); ``` @@ -4396,6 +4409,8 @@ The predefined subtraction operators are listed below. The operators all subtrac ```csharp int operator –(int x, int y); uint operator –(uint x, uint y); + nint operator –(nint x, nint y); + nuint operator –(nuint x, nuint y); long operator –(long x, long y); ulong operator –(ulong x, ulong y ``` @@ -4521,6 +4536,8 @@ The predefined shift operators are listed below. ```csharp int operator <<(int x, int count); uint operator <<(uint x, int count); + nint operator <<(nint x, int count); + nuint operator <<(nuint x, int count); long operator <<(long x, int count); ulong operator <<(ulong x, int count); ``` @@ -4533,6 +4550,8 @@ The predefined shift operators are listed below. ```csharp int operator >>(int x, int count); uint operator >>(uint x, int count); + nint operator >>(nint x, int count); + nuint operator >>(nuint x, int count); long operator >>(long x, int count); ulong operator >>(ulong x, int count); ``` @@ -4619,31 +4638,43 @@ The predefined integer comparison operators are: ```csharp bool operator ==(int x, int y); bool operator ==(uint x, uint y); +bool operator ==(nint x, nint y); +bool operator ==(nuint x, nuint y); bool operator ==(long x, long y); bool operator ==(ulong x, ulong y); bool operator !=(int x, int y); bool operator !=(uint x, uint y); +bool operator !=(nint x, nint y); +bool operator !=(nuint x, nuint y); bool operator !=(long x, long y); bool operator !=(ulong x, ulong y); bool operator <(int x, int y); bool operator <(uint x, uint y); +bool operator <(nint x, nint y); +bool operator <(nuint x, nuint y); bool operator <(long x, long y); bool operator <(ulong x, ulong y); bool operator >(int x, int y); bool operator >(uint x, uint y); +bool operator >(nint x, nint y); +bool operator >(nuint x, nuint y); bool operator >(long x, long y); bool operator >(ulong x, ulong y); bool operator <=(int x, int y); bool operator <=(uint x, uint y); +bool operator <=(nint x, nint y); +bool operator <=(nuint x, nuint y); bool operator <=(long x, long y); bool operator <=(ulong x, ulong y); bool operator >=(int x, int y); bool operator >=(uint x, uint y); +bool operator >=(nint x, nint y); +bool operator >=(nuint x, nuint y); bool operator >=(long x, long y); bool operator >=(ulong x, ulong y); ``` @@ -5098,16 +5129,22 @@ The predefined integer logical operators are: ```csharp int operator &(int x, int y); uint operator &(uint x, uint y); +nint operator &(nint x, nint y); +nuint operator &(nuint x, nuint y); long operator &(long x, long y); ulong operator &(ulong x, ulong y); int operator |(int x, int y); uint operator |(uint x, uint y); +nint operator |(nint x, nint y); +nuint operator |(nuint x, nuint y); long operator |(long x, long y); ulong operator |(ulong x, ulong y); int operator ^(int x, int y); uint operator ^(uint x, uint y); +nint operator ^(nint x, nint y); +nuint operator ^(nuint x, nuint y); long operator ^(long x, long y); ulong operator ^(ulong x, ulong y); ``` From b5694becf522030dc8f42798dc7cd7e7836b4eed Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 7 Mar 2026 12:37:19 -0500 Subject: [PATCH 3/4] Support Numeric IntPtr --- standard/conversions.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/standard/conversions.md b/standard/conversions.md index 39acaacc0..8d0ef9004 100644 --- a/standard/conversions.md +++ b/standard/conversions.md @@ -115,8 +115,6 @@ All identity conversions are symmetric. If an identity conversion exists from `T In most cases, an identity conversion has no effect at runtime. However, since floating point operations may be performed at higher precision than prescribed by their type ([§8.3.7](types.md#837-floating-point-types)), assignment of their results may result in a loss of precision, and explicit casts are guaranteed to reduce precision to what is prescribed by the type ([§12.9.8](expressions.md#1298-cast-expressions)). -There is an identity conversion between `nint` and `System.IntPtr`, and between `nuint` and `System.UIntPtr`. - For the compound types array, nullable type, constructed type, and tuple, there is an identity conversion between native integers ([§8.3.6](types.md#836-integral-types)) and their underlying types. ### 10.2.3 Implicit numeric conversions From 923ea69a3e1dc6b62e290c88a87c5713b0d80e28 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 7 Mar 2026 12:48:16 -0500 Subject: [PATCH 4/4] Support Numeric IntPtr --- standard/types.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/standard/types.md b/standard/types.md index b4bd2f20d..dadbf4144 100644 --- a/standard/types.md +++ b/standard/types.md @@ -273,7 +273,7 @@ A struct type is a value type that can declare constants, fields, methods, prope ### 8.3.5 Simple types -Except for `nint` and `nuint`, the simple types are aliases for predefined `struct` types in the `System` namespace, as described in the table below. +The simple types are aliases for predefined `struct` types in the `System` namespace, as described in the table below. **Keyword** | **Aliased type** ----------- | ------------------ @@ -283,8 +283,8 @@ Except for `nint` and `nuint`, the simple types are aliases for predefined `stru `ushort` | `System.UInt16` `int` | `System.Int32` `uint` | `System.UInt32` - `nint` | none; see below - `nuint` | none; see below + `nint` | `System.IntPtr` + `nuint` | `System.UIntPtr` `long` | `System.Int64` `ulong` | `System.UInt64` `char` | `System.Char` @@ -293,7 +293,7 @@ Except for `nint` and `nuint`, the simple types are aliases for predefined `stru `bool` | `System.Boolean` `decimal` | `System.Decimal` -Every simple type has members. Each simple type that is an alias for a predefined struct type, has that struct type’s members. +Every simple type has members. Each simple type has its aliased struct type’s members. > *Example*: `int` has the members declared in `System.Int32` and the members inherited from `System.Object`, and the following statements are permitted: >